2017-01-17 2 views
0

코드 :T-SQL - 날짜 시간 간격 배포

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

필요 나는 당신의 선언 문 이외의 코드가 표시되지 않는 경우. 그러나'@DED'가 될 때까지 1 일을 '@ SD'에 추가 할 수 있어야합니다. –

답변

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

이보십시오. 니가 원하는 것을 얻어야한다.

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 
+1

집합 기반 작업을 사용할 수있는 경우 루프를 사용해야하는 이유는 무엇입니까? [루프가없는 세트 또는 시퀀스 생성 - 1 부 - Aaron Bertrand - 2013-01-16] (https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1) – SqlZim

+0

좋은 포인트. 이것은 첫 번째 생각이었고 나는 그것을 가장 단순하게 유지하려고 노력했습니다. 제안 해 주셔서 감사합니다! –

1

는 2 개 범위 사이의 행을 삽입하기위한 다음의 접근 방식을

  1. 사용 datediff 함수를 사용한다.

  2. datetime 값의 시간 만 업데이트하십시오.

데모 : -

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 

결과 : -

enter image description here

+1

집합 기반 작업을 사용할 수있는 경우 루프를 사용해야하는 이유는 무엇입니까? [루프가없는 세트 또는 시퀀스 생성 - 1 부 - Aaron Bertrand - 2013-01-16] (https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1) – SqlZim

1

나는 종종 동적 날짜/시간 범위를 만들 TVF를 사용합니다. 집계 테이블도 트릭을 할 것입니다. UDF는 재귀 CTE보다 빠르며 매개 변수로 구동됩니다. 날짜 범위, DatePart 및 Increment를 제공합니다. 예를 들면 :

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](@[email protected],@[email protected],'DD',1) 

반환

enter image description here

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<[email protected] 
) 
/* 
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) 
*/