Tsql 将日期范围转换为每天记录的SQL查询 要求 我有一个数据表,可以保存日期范围内的数据。 允许每个记录与以前的记录重叠。记录有一个CreatedOn datetime列。 如果需要,新记录可以定义自己的日期范围,因此可以重叠多个旧记录。 每个新的重叠记录都会覆盖其重叠的旧记录的设置。 结果集

Tsql 将日期范围转换为每天记录的SQL查询 要求 我有一个数据表,可以保存日期范围内的数据。 允许每个记录与以前的记录重叠。记录有一个CreatedOn datetime列。 如果需要,新记录可以定义自己的日期范围,因此可以重叠多个旧记录。 每个新的重叠记录都会覆盖其重叠的旧记录的设置。 结果集,tsql,sql-server-2008-r2,Tsql,Sql Server 2008 R2,我需要得到的是使用记录重叠的任何日期范围的每日数据。它应该每天返回一条记录,其中包含该特定日期的相应数据 要将范围转换为我想使用的天数,请使用用户定义的函数UDF获取范围内每天的数据,但我想知道是否还有其他更好*甚至更快的方法,因为我使用的是最新的SQL Server 2008 R2 存储数据 想象一下,我存储的数据如下所示 ID | RangeFrom | RangeTo | Starts | Ends | CreatedOn (not providing data) ---|------

我需要得到的是使用记录重叠的任何日期范围的每日数据。它应该每天返回一条记录,其中包含该特定日期的相应数据

要将范围转换为我想使用的天数,请使用用户定义的函数UDF获取范围内每天的数据,但我想知道是否还有其他更好*甚至更快的方法,因为我使用的是最新的SQL Server 2008 R2

存储数据 想象一下,我存储的数据如下所示

ID | RangeFrom | RangeTo  | Starts | Ends  | CreatedOn (not providing data)
---|-----------|----------|--------|-------|-----------
1  | 20110101  | 20110331 | 07:00  | 15:00
2  | 20110401  | 20110531 | 08:00  | 16:00
3  | 20110301  | 20110430 | 06:00  | 14:00 <- overrides both partially
后果 如果我想获得2011年1月1日至2001年5月31日的数据,结果表应如下所示:

DayDate | Starts | Ends
--------|--------|------
20110101| 07:00  | 15:00  <- defined by record ID = 1
20110102| 07:00  | 15:00  <- defined by record ID = 1
...                          many rows omitted for obvious reasons
20110301| 06:00  | 14:00  <- defined by record ID = 3
20110302| 06:00  | 14:00  <- defined by record ID = 3
...                          many rows omitted for obvious reasons
20110501| 08:00  | 16:00  <- defined by record ID = 2
20110502| 08:00  | 16:00  <- defined by record ID = 2
...                          many rows omitted for obvious reasons
20110531| 08:00  | 16:00  <- defined by record ID = 2

事实上,因为您正在处理日期,所以日历表会更有用

Declare @StartDate date
Declare @EndDate date

;With Calendar As
    (
    Select @StartDate As [Date]
    Union All
    Select DateAdd(d,1,[Date])
    From Calendar
    Where [Date] < @EndDate
    )
Select ...
From Calendar
    Left Join MyTable
        On Calendar.[Date] Between MyTable.Start And MyTable.End
Option ( Maxrecursion 0 );
加成

错过了你原来帖子中关于特朗普规则的部分:

Set DateFormat MDY;
Declare @StartDate date = '20110101';
Declare @EndDate date = '20110501';

-- This first CTE is obviously to represent
-- the source table
With SampleData As 
    (
    Select 1 As Id
        , Cast('20110101' As date) As RangeFrom
        , Cast('20110331' As date) As RangeTo
        , Cast('07:00' As time) As Starts
        , Cast('15:00' As time) As Ends
        , CURRENT_TIMESTAMP As CreatedOn
    Union All Select 2, '20110401', '20110531', '08:00', '16:00', DateAdd(s,1,CURRENT_TIMESTAMP )
    Union All Select 3, '20110301', '20110430', '06:00', '14:00', DateAdd(s,2,CURRENT_TIMESTAMP )
    )
    , Calendar As
    (
    Select @StartDate As [Date]
    Union All
    Select DateAdd(d,1,[Date])
    From Calendar
    Where [Date] < @EndDate
    )
    , RankedData As
    (
    Select C.[Date]
        , S.Id
        , S.RangeFrom, S.RangeTo, S.Starts, S.Ends
        , Row_Number() Over( Partition By C.[Date] Order By S.CreatedOn Desc ) As Num
    From Calendar As C
        Join SampleData As S
            On C.[Date] Between S.RangeFrom And S.RangeTo
    )
Select [Date], Id, RangeFrom, RangeTo, Starts, Ends
From RankedData
Where Num = 1   
Option ( Maxrecursion 0 );
简言之,我对所有样本数据进行排序,优先选择与同一日期重叠的较新行。

既然可以在内存中做得更好,为什么还要在DB中进行排序 这是我最终使用的解决方案,在数据传输、速度和资源方面似乎是最合理的

获取从DB到中端的实际范围定义数据量较小 生成特定日期范围的内存日历的速度比以DB为单位的快 将这些DB定义放在比DB更简单、更快的位置
就这样。我意识到,如果内存中有可执行代码,可以更快、更高效地执行相同的操作,那么在DB中使某些事情复杂化是不值得的。

一个具有两个参数的用户定义函数,可以更好地返回日期表!:但这只是问题的一部分。这将把我的日期范围转换为日期记录。但是我如何解释重叠的记录呢?@robertkoritnik-首先,一些模式信息、样本输入和预期输出会有所帮助。第二,你是想在白天找到多行在同一天重叠的场景吗?@Thomas:更新了我的问题,或者更好地说是添加了表结构和结果表结构…@Thomas:Close但不完全相同。每天都会有多条记录,覆盖的数量与覆盖+1的数量相同。这是不可取的。根据AD4,当有覆盖时,更新的记录优先。@Robert-是的,我忽略了第四个要求。我注意到在你的样本输出中你每天有一行。如果同一天有两行重叠,那么只显示一行或同时显示两行的规则是什么?@Thomas:见我问题中的广告4。每个新记录都会覆盖与之重叠的旧记录。