2016-11-03 12 views
1

私は以下のクエリを持っており、2 datetimeの間に30分間隔でdatetimeを取得したいと思います。基本的に私はそれを持っていますが、時間制限が24時間を超える場合には制限があり、結果が返されません。例えばmssql 30分間隔beteen 2 datetime

@DateTime1 = 24/11/2016 18:00:00 
@DateTime2 = 25/11/2016 06:00:00 

結果:(フォーマットの "DD-HH:MM")

24-18:00 
24-18:30 
24-19:00 
24-19:30 
24-20:00 
... 
... 
25-05:00 
25-05:30 
25-06:00 

私が試したどのような。

SELECT  number, DATEADD(MINUTE, number, @DateTime1) AS DateTimeLine, DATEPART(DAY, DATEADD(MINUTE, number, @DateTime1)) AS Days, DATEPART(MONTH, 
DATEADD(MINUTE, number, @DateTime1)) AS Months, DATEPART(YEAR, DATEADD(MINUTE, number, @DateTime1)) AS Years, DATEPART(HOUR, DATEADD(MINUTE, 
number, @DateTime1)) AS Hours, DATEPART(MINUTE, DATEADD(MINUTE, number, @DateTime1)) AS Minute, CAST(DATEADD(MINUTE, number, @DateTime1) 
AS DATE) AS Date, CAST(DATEADD(MINUTE, number, @DateTime1) AS TIME) AS Time 

FROM   master.dbo.spt_values 

WHERE  (type = 'P') AND (DATEPART(MINUTE, DATEADD(MINUTE, number, @DateTime1)) = 30 OR DATEPART(MINUTE, DATEADD(MINUTE, number, @DateTime1)) = 0) AND (DATEADD(MINUTE, number, @DateTime1) <= @DateTime2) 

ORDER BY number 
+2

あなた自身が日付の上に島とのギャップを計算見つけた場合は、たくさんの範囲、私は非常にカレンダーテーブルを作成することをお勧め。それは非常に助けになります。 –

答えて

0

私は動的な日付/時刻範囲を生成するTVFを持っています。それは再帰的なcteよりも速く、より柔軟に思える。日付範囲、希望のDatePart、および増分を渡します。

Declare @DateTime1 DateTime = '2016-11-24 18:00:00' 
Declare @DateTime2 DateTime = '2016-11-25 06:00:00' 

Select Format(RetVal,'dd-HH:mm') from [dbo].[udf-Range-Date](@DateTime1,@DateTime2,'MI',30) 

戻り

24-18:00 
24-18:30 
24-19:00 
24-19:30 
24-20:00 
24-20:30 
24-21:00 
24-21:30 
24-22:00 
24-22:30 
24-23:00 
24-23:30 
25-00:00 
.... 
25-04:30 
25-05:00 
25-05:30 
25-06:00 

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

ありがとうございました!!! –

+0

@Renéお手伝いをします。 –

0

再帰的共通表式[CTE]を使用することは、きれいな方法の1つです。書式設定では、FORMAT()をSQL-Server 2012+で表示していますが、FORMAT()はパフォーマンスに影響を与える可能性があるため、DATEPARTなどを使用することを検討することもできます。

@ RossBushのコメントに同意すると、カレンダー(日付)を生成したくて、時間の次元がこれらの目的に非常に役立ちます。

DECLARE @DateTime1 DATETIME = '2016/11/24 18:00:00' 
DECLARE @DateTime2 DATETIME = '2016/11/25 06:00:00' 

;WITH cte30MinIncrements AS (
    SELECT @DateTime1 as DT 

    UNION ALL 

    SELECT DATEADD(MINUTE,30,DT) 
    FROM 
     cte30MinIncrements 
    WHERE DATEADD(MINUTE,30,DT) <= @DateTime2 
) 

SELECT 
    * 
    ,FORMAT(DT,'dd-HH:mm') as Formated 
FROM 
    cte30MinIncrements 
+0

基本的にカウントしているcteがあります。これは設定されているように見えますが、実際はそうではありません。 http://www.sqlservercentral.com/articles/T-SQL/74118/ –

+0

@SeanLangeとあなたのポイントは、それがOPの目的のために十分な演奏ができないことに基づいて設定されていないためですか?私はそれがベースに設定されていると主張したことはありませんし、この技術はかなり一般的です私の答えが特定されているように、パフォーマンス目的やその他の用途には、カレンダー(日付)ディメンションと時間ディメンションを使用することをお勧めします。 – Matt

+0

私はそれが十分に演奏することができないとは言いませんでした。ループやカーソルは、十分なパフォーマンスを発揮することがあります。多くの人々は、再帰的なcteをカウントすることは実際にはカーソルと同じことをしていることに気づいていません。それをもたらすことの私のポイントは、人々がそれを理解できるようにすることです。何かが共通しているからといって、それを行うのが最善の方法であるとは限りません。カーソルはこの種のものでは非常に一般的ですが、私はこれらのソリューションもパフォーマンスの観点からは最高ではないと警告します。 –

0

これが機能するか確認してください。

declare @DateTime1 DateTime = '2016-11-24 18:00:00' 
declare @DateTime2 DateTime = '2016-11-25 18:00:00' 

declare @Interval DateTime = @DateTime1 
declare @vartmptable table(DT DateTime) 

While (@Interval < @DateTime2) 
begin 
--select @Interval, FORMAT(@Interval,'dd-HH:mm') 
insert into @vartmptable select @Interval 
set @Interval = DATEADD(mi,30,@Interval) 

end 

select FORMAT(DT,'dd-HH:mm') from @vartmptable 
+1

ループはこれを処理する良い方法ではありません。 –

+0

具体的な理由はありますか? – Vicky1729

+1

ループはひどく非効率です。それらは、非常に小さいセットを除いて避けるべきです。いくつかの管理やメールのマージのようなことは、ループが必要な時だけです。 –

1

集計表は、このタイプのものを処理するのに最適な方法です。私はspt_valuesの使用を避けるために1つのビューを保持します。

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 

コードが本当にシンプルになります。少量のdatemathとvoila。

declare @DateTime1 datetime = '2016/11/24 18:00:00' 
    , @DateTime2 datetime = '2016/11/25 06:00:00' 

select FORMAT(DATEADD(minute, (t.N - 1) * 30, @DateTime1), 'dd-HH:mm') 
from cteTally t 
where t.N <= (DATEDIFF(hour, @DateTime1, @DateTime2) * 2) + 1 
0

何が必要か?必要に応じて変数/固定値を使用できます。

WITH CTE_Numbers 
AS (
    SELECT n = 1 

    UNION ALL 

    SELECT n + 1 
    FROM CTE_Numbers 
    WHERE n < 100 
    ) 
SELECT FORMAT(DATEADD(mi, n * 30, '2016/11/03'),'dd-HH:mm') 
FROM CTE_Numbers 
+2

ここで注意してください。このようにカウントするためにrcteを使用することは、カーソルとほぼ同じことです。 http://www.sqlservercentral.com/articles/T-SQL/74118/ –

+1

@Renéなぜこのソリューションが最適だとお考えですか?集計表を使用する場合は、Seanのビューを使用するか、マテリアライズされた集計表を使用します。再帰的なcteを使用している場合、比較のために実際のdatetimeを取得することができたら、なぜ集計表を使用するのですか?しかし、猫の皮膚にはたくさんの方法があります。あなたがこのように好きなら、それを求めてください。 – Matt

+0

申し訳ありませんが、間違ったコメンテントに書きました! –

関連する問題