代码:
DECLARE @SD DATE = '2017-01-01'
,@ED DATE = '2017-01-07'
,@ST TIME = '08:00:00'
,@ET TIME = '16:00:00';
DECLARE @DT_T TABLE (SDT DATETIME, EDT DATETIME)
目标: 要合并开始/结束日期和开始/结束时间(@ SD / @ ED和@ ST / @ ET)并创建一个表格,其中包含StartDateTime和EndDateTime之间的间隙,如下面所需的输出所示。
期望输出
/* @DT_T Data
SDT EDT
2017-01-01 08:00:00 2017-01-01 16:00:00
2017-01-02 08:00:00 2017-01-02 16:00:00
2017-01-03 08:00:00 2017-01-03 16:00:00
2017-01-04 08:00:00 2017-01-04 16:00:00
2017-01-05 08:00:00 2017-01-05 16:00:00
2017-01-06 08:00:00 2017-01-06 16:00:00
2017-01-07 08:00:00 2017-01-07 16:00:00
*/
我正在尝试使用数字表,但到目前为止还没有到达任何地方。
答案 0 :(得分:1)
这样的东西? rextester:http://rextester.com/ULTV27021
declare @sd date = '2017-01-01'
,@ed date = '2017-01-07'
,@st_hour int = 8
,@et_hour int = 16;
declare @dt_t table (sdt datetime, edt datetime);
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, d as (
select
sdt=dateadd(hour,@st_hour,convert(datetime,dateadd(day, row_number() over (order by (select 1)) -1,@sd)))
, edt=dateadd(hour,@et_hour,convert(datetime,dateadd(day, row_number() over (order by (select 1)) -1,@sd)))
from n as deka
cross join n as hecto
cross join n as kilo /* 2.73 years */
--cross join n as [10k] /* 27.3 years */
)
insert into @dt_t (sdt,edt)
select top (datediff(day,@sd,@ed)+1)
sdt
, edt
from d
order by sdt;
select * from @dt_t
注意: rextester的日期默认输出格式为dd.MM.yyyy
答案 1 :(得分:1)
试试这个。应该得到你想要的东西。
DECLARE @SD DATE = '2017-01-01'
,@ED DATE = '2017-01-07'
,@ST TIME = '08:00:00'
,@ET TIME = '16:00:00';
DECLARE @DT_T TABLE (SDT DATETIME, EDT DATETIME)
Declare @i int = 0
While (@SD < @ED)
Begin
Insert Into @DT_T(SDT, EDT)
Select Cast(Convert(varchar(10),DateAdd(Day,@i,@SD),21) + ' ' + Convert(varchar(8),@ST,21) as datetime), Cast(Convert(varchar(10),DateAdd(Day,@i,@SD),21) + ' ' + Convert(varchar(10),@ET,21) as DateTime)
Set @i = @i + 1
IF (DateAdd(Day,@i,@SD) = @ED)
Break
Else
Continue
END
Insert Into @DT_T(SDT, EDT)
Select Cast(Convert(varchar(10),@ED,21) + ' ' + Convert(varchar(8),@ST,21) as datetime), Cast(Convert(varchar(10),@ED,21) + ' ' + Convert(varchar(10),@ET,21) as DateTime)
Select SDT, EDT From @DT_T
答案 2 :(得分:1)
使用下一个方法
使用datediff函数在2之间插入行 范围。
仅更新日期时间值的时间。
<强>演示: - 强>
DECLARE @SD DATE = '2017-01-01'
,@ED DATE = '2017-01-07'
,@ST TIME = '08:00:00'
,@ET TIME = '16:00:00';
DECLARE @DT_T TABLE (SDT DATETIME, EDT DATETIME)
DECLARE @start int
set @start = 0
while @start <= datediff(day,@SD,@ED)
begin
insert into @DT_T values
( dateadd(day,@start, @SD) ,
dateadd(day,@start, @SD))
set @start = @start + 1
end
UPDATE @DT_T
SET SDT = DATEADD(HOUR, 8, CAST(CAST(SDT AS DATE) AS DATETIME)) ,
EDT = DATEADD(HOUR, 16, CAST(CAST(EDT AS DATE) AS DATETIME))
select * from @DT_T
<强>结果: - 强>
答案 3 :(得分:1)
我经常使用TVF创建动态日期/时间范围。计数表也可以解决这个问题。 UDF可以比递归CTE更快并且是参数驱动的。您提供日期范围,DatePart和增量。例如:
Declare @D1 datetime = '2017-01-01'
Declare @D2 datetime = '2017-01-07'
Declare @T1 datetime = '08:00'
Select RetSeq
,STD = RetVal
,EDT = DateAdd(HOUR,8,RetVal)
From [dbo].[udf-Range-Date](@D1+@T1,@D2+@T1,'DD',1)
返回
UDF(如果需要)
CREATE FUNCTION [dbo].[udf-Range-Date] (@R1 datetime,@R2 datetime,@Part varchar(10),@Incr int)
Returns Table
Return (
with cte0(M) As (Select 1+Case @Part When 'YY' then DateDiff(YY,@R1,@R2)/@Incr When 'QQ' then DateDiff(QQ,@R1,@R2)/@Incr When 'MM' then DateDiff(MM,@R1,@R2)/@Incr When 'WK' then DateDiff(WK,@R1,@R2)/@Incr When 'DD' then DateDiff(DD,@R1,@R2)/@Incr When 'HH' then DateDiff(HH,@R1,@R2)/@Incr When 'MI' then DateDiff(MI,@R1,@R2)/@Incr When 'SS' then DateDiff(SS,@R1,@R2)/@Incr End),
cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a, cte1 b, cte1 c, cte1 d, cte1 e, cte1 f, cte1 g, cte1 h ),
cte3(N,D) As (Select 0,@R1 Union All Select N,Case @Part When 'YY' then DateAdd(YY, N*@Incr, @R1) When 'QQ' then DateAdd(QQ, N*@Incr, @R1) When 'MM' then DateAdd(MM, N*@Incr, @R1) When 'WK' then DateAdd(WK, N*@Incr, @R1) When 'DD' then DateAdd(DD, N*@Incr, @R1) When 'HH' then DateAdd(HH, N*@Incr, @R1) When 'MI' then DateAdd(MI, N*@Incr, @R1) When 'SS' then DateAdd(SS, N*@Incr, @R1) End From cte2 )
Select RetSeq = N+1
,RetVal = D
From cte3,cte0
Where D<=@R2
)
/*
Max 100 million observations -- Date Parts YY QQ MM WK DD HH MI SS
Syntax:
Select * from [dbo].[udf-Range-Date]('2016-10-01','2020-10-01','YY',1)
Select * from [dbo].[udf-Range-Date]('2016-01-01','2017-01-01','MM',1)
*/