2017-01-17 8 views
0

コード:T-SQL - 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) 

目標: (@ 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'までは' @SD'に1日追加するだけです。 –

答えて

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つの 範囲の間の行を挿入するためdatediff関数を使用し、次のアプローチを

  1. を使用します。

  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) 
*/