当前位置: 首页 > 知识库问答 >
问题:

SQL开始时间结束时间查询

魏臻
2023-03-14

我有这样的桌子

CREATE TABLE Table_Status
(
Status VARCHAR(10) NOT NULL,
StartTime DATETIME NOT NULL, 
EndTime DATETIME NOT NULL
); 

数据如下所示,开始时间和结束时间是连续的时间跨度:

Status1 2007-10-16 18:38:25.000 2007-10-17 05:30:22.000 
Status2 2007-10-17 05:30:22.000 2007-10-17 18:48:46.000
Status2 2007-10-17 18:48:46.000 2007-10-17 21:48:46.000
Status1 2007-10-17 21:48:46.000 2007-10-18 08:11:59.000

因此,如果用户传递两个参数,则可以在任意时间段内选择*

SET @From = '2007-10-17 00:00:00.000'
SET @To = '2007-10-17 23:59:59.000' 

它应该以如下方式返回表:

Status1 2007-10-17 00:00:00.000 2007-10-17 05:30:22.000
Status2 2007-10-17 05:30:22.000 2007-10-17 21:48:46.000
Status1 2007-10-17 21:48:46.000 2007-10-17 23:59:59.000

你看,棘手的部分是将原始的时间跨度削减到用户定义的时间跨度(@from-@To),我已经为此奋斗了一整天。请指教。

提前非常感谢你!!!

共有3个答案

班展
2023-03-14

如前所述:由于您的日期已经是连续的,您可以简单地将开始和结束时间的可能位置统一在一起。

SET @From = '2007-10-17 00:00:00'
SET @To = '2007-10-17 23:59:59'

-- Intervals where from is included, but to is not
SELECT 'A' Union_Case, Status, @From StartTime, EndTime FROM Table_Status 
    WHERE StartTime < @From AND @From <= EndTime AND EndTime < @To
  UNION 
-- Intervals where @to and @from are incased in the interval
SELECT 'B', Status, @From, @To FROM Table_Status WHERE StartTime < @From AND EndTime >= @To
  UNION  
-- Intervals where @from is before start and @to is after end
SELECT 'C', Status, StartTime, EndTime FROM Table_Status WHERE StartTime > @From AND StartTime <= @To AND EndTime < @To 
  UNION 
-- intervals where @from is before start but @to ends within
SELECT 'D',  Status, StartTime, @To FROM Table_Status WHERE @From <= StartTime AND EndTime > @To
  ORDER BY 3, 4
蒋畅
2023-03-14

我面临着类似的情况,我能够解决的方法是:

DECLARE @TimeStamp as DateTimeType
SET @TimeStamp = cast('2016-10-13 00:00:00.000' as datetime)
DECLARE @DayNum as ApsDayOrdinalType = DATEPART(dw,@TimeStamp)
DECLARE @Time as Time = cast(@TimeStamp as time)
DECLARE @DefaultTime as Time = CAST('00:00' as time)

SELECT @DayNum,@Time,@DefaultTime
-- CTEs don't work pretty well with inline data transformation :'(
DECLARE @WorkCenterShifts as table(
  WorkCenter varchar(15),
  ShiftId varchar(15),
  StartDateTime DateTime,
  EndDateTime DateTime
)

INSERT INTO @WorkCenterShifts
SELECT 
  wc
  ,shiftid
  ,CAST(CAST(DateAdd(dd,-(@DayNum - sday),@TimeStamp) as date) as varchar) +' '+ cast(stime as varchar)
  ,CAST(CAST(DateAdd(dd,(@DayNum - eday),@TimeStamp) as date) as varchar) +' '+ cast(etime as varchar)
FROM workcentershiftview 
WHERE wc = @wc
  and @DayNum >= IsNull(sday,1) 
  and @DayNum <= IsNull(eday,7) 

其中“workcentershiftview”返回如下数据:

WC      ShiftId sDay    eDay    sTime   eTime
MXMCE2  2nd9    6       2       16:00   06:30
MXMCE2  1st9.5  6       6       06:30   16:00
MXMCE2  2nd9    5       6       16:00   06:30
MXMCE2  1st9.5  5       5       06:30   16:00
MXMCE2  2nd9    4       5       16:00   06:30

从那里,我终于可以创建一个简单的查询,如下所示:

SELECT * FROM @WorkCenterShifts
WHERE @TimeStamp between StartDateTime and EndDateTime

得到这样的结果:

WorkCencer    ShiftId     StartDateTime               EndDateTime
MXMCE2        2nd9        2016-10-12 16:00:00.000     2016-10-13 06:30:00.000

希望这对其他人有用:)

顾嘉纳
2023-03-14

有两个部分可以获得您正在寻找的结果集。

>

  • 将具有相同“状态”值的所有连续日期合并在一起
  • 返回具有以下内容的组合结果集:

    • 完全在您的日期起止参数范围内的所有范围
    • 与起始/结束参数开头部分重叠的计算范围
    • 与“从/到”参数结尾部分重叠的计算范围

    对于日期合并,您可以查看以下两个链接,了解合并连续日期范围的方法:

    http://www.sqlservercentral.com/Forums/Topic1364849-392-1.aspx

    http://sqlmag.com/blog/solutions-packing-date-and-time-intervals-puzzle

    我用了其中一个最易读的例子。然而,如果您正在寻找性能更好的查询,您可以查看其他查询。

    下面是一个示例查询,返回示例中的结果集:

    合并具有相同状态的连续日期行

    with all_times (time_type,date_range_part,status) as (
    select 'start',
           starttime,
           status
    from table_status
    union all
    select 'end',
           endtime,      
           status
    from table_status),
    
    ordered_starts as (
    select date_range_part,
           status,
           row_number() over(partition by status order by date_range_part, time_type desc) as rnboth,
           2*(row_number() over(partition by status,time_type order by date_range_part))-1 as rnstartend
    from all_times),
    
    ordered_ends as (
    select date_range_part,
           status,
           row_number() over(partition by status order by date_range_part desc,time_type) as rnbothrev,
           2*(row_number() over(partition by status,time_type order by date_range_part desc))-1 as rnstartendrev
    from all_times),
    
    starts as (
    select date_range_part,
           status,
           row_number() over(partition by status order by date_range_part) as rn
    from ordered_starts
    where rnboth=rnstartend),
    
    ends as (
    select date_range_part,
           status,
           row_number() over(partition by status order by date_range_part) as rn
    from ordered_ends
    where rnbothrev=rnstartendrev)
    
    select 
    s.status,
    s.date_range_part [start_time],
    e.date_range_part [end_time]
    into #table_status_merged
    from starts s
    inner join ends e on e.status=s.status and e.rn=s.rn and s.date_range_part<=e.date_range_part
    order by s.date_range_part;
    

    返回一个结果集,该结果集的所有范围都完全在日期参数内、计算的开始范围和计算的结束范围

    declare @from datetime
    declare @to datetime
    
    set @from = '2007-10-17 00:00:00.000'
    set @to = '2007-10-17 23:59:59.000'
    
    select
    [status],
    @from,
    end_time
    from #table_status_merged
    where start_time < @from
    and end_time <= @to
    union all
    select
    [status],
    start_time,
    end_time
    from #table_status_merged
    where start_time >= @from
    and end_time <= @to
    union all
    select
    [status],
    start_time,
    @to
    from #table_status_merged
    where start_time >= @from
    and end_time > @to
    
    drop table #table_status_merged
    

  •  类似资料:
    • 问题内容: 我有两个表: 我希望将事件数据添加到视频数据中,以便为每个事件获取视频文件名。记录器字段用于指定在事件发生时可操作的记录器,并协助多个记录器同时记录视频。 如果我不关心没有视频的事件,那很好(我可以获取SQL),但是在我的情况下,我希望显示最接近的视频文件名和秒数差异。 编辑 样本数据 大事记 视频 结果(EventID,VideoID,文件名,IsBetween,secondsDif

    • 我想从JavaGUI到数据库获取startTime和endTime的值。 电脑座位班 Cobadatabase类 这里的问题是,当单击登录按钮时,开始时间显示在我的数据库中的开始时间和结束时间列上。当单击注销按钮时,将在数据库中创建另一个行,该行在starTime和endTime列上都包含endTime。我想知道为什么会这样...

    • 是否可以跟踪卡桑德拉的“预订”? 基本上,我的大多数查询将涉及一个和一个,我希望在其中找到与该时间相交的所有保留。 我的模式如下所示: 我输入了一些数据,如下所示: 我正在尝试这样的查询: 我得到一个这样的错误: 我认为这是可以做到的,因为在这个SO问题中似乎是这样的:在cassandra中存储时间范围 但是,架构没有发布,我们也没有使用pycassa,而且我似乎无法弄清楚如何将其映射到CQL。

    • 得到的包含我指定的6秒,后跟8或9秒的空音频。我的指挥有问题吗? 编辑: 表示并给我一个文件,从10秒开始有8秒的音频,然后有9或10秒的静默。 我的目标是通过REST API将这个6秒的文件流到前端。我希望用户能够正确下载此文件。理想情况下,它不会有不一致的元数据(14秒而不是6秒)。

    • 问题内容: 这是我的Django模型: 我需要找到一个在给定日期范围内在办公室花费最多时间的工人。如何从Django查询中的timeIn和timeOut字段计算持续时间? 编辑:我不想使用另一个属性 持续时间, 因为这似乎是多余的。除了使用原始查询或持续时间属性,还有其他方法吗? 问题答案: Django 1.10引入了通过ORM本地执行日期/时间差异的功能。此查询将为您提供最长的转变: 您可以根