给出下表:
create table xx (start_time datetime, end_time datetime, label varchar(100));
insert into xx values
('20180101 08:00', '20180103 08:00', 'test 1'),
('20180101 06:30', '20180101 08:00', 'test 2'),
('20180101 10:00', '20180102 08:00', 'test 3');
我必须生成一个列表,其中记录的重复次数与start_time和end_time之间的天数一样多。 预期结果是:
run_date label
2018-01-01 test 1
2018-01-02 test 1
2018-01-03 test 1
2018-01-01 test 2
2018-01-01 test 3
2018-01-02 test 3
如何以高效的方式实现这一目标(可能没有任何丑陋的光标)? 动态时间间隔未定义(1到10天之间) 源表非常大(几百万条记录)
答案 0 :(得分:2)
如果您没有日历表,则一种方法是与CROSS APPLY一致的临时计数表
示例强>
Select run_date=cast(B.D as date)
,A.label
from XX A
Cross Apply (
Select Top (DateDiff(DAY,Start_Time,End_Time)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),Start_Time)
From master..spt_values n1 -- ,master..spt_values n2 -- remove comment if span > 6 years
) B
<强>返回强>
run_date label
2018-01-01 test 1
2018-01-02 test 1
2018-01-03 test 1
2018-01-01 test 2
2018-01-01 test 3
2018-01-02 test 3
修改强>
刚注意到数百万条记录。使用JOIN到日历表
可能会更好答案 1 :(得分:1)
这是Numbers表派上用场的地方之一。 Here Aaron Bertrand的一篇文章谈到了这些表格。
基本上,您创建一个表Numbers
,其中包含一行Number
,其中包含N行,从0(或1)到您想要的最大数量(以及基础类型支持)。然后你可以轻松加入:
SELECT CONVERT(date, xx.start_time + n.Number) AS RunningDate, xx.label
FROM xx
INNER JOIN Numbers n ON n.Number <= DATEDIFF(DAY, xx.start_time, xx.end_time)
此解决方案假设Numbers表从0开始。应略微修改以允许从1开始的表相同。