2016-12-01 65 views
0

這是一個08:00的人口普查,它將根據開始和結束日期時間捕捉任何在08:00房間的人。計算日期時間間隔多少次08:00

我有一個開始日期時間,並最終結束日期時間,但我需要顯示在沒有結束日期時間的下一天日期。

如果開始日期時間是
< = 08:00
和端日期時間是在同一天
那麼這將是1,否則將不被顯示。

如果最終日期時間
不是null,任何一天開始日期時間
後,那麼這將是1在接下來的日子裏,直到結束日期時間。
但是最後的結束日期時間必須大於或等於08:00,否則不會在當天顯示。

如果最終日期時間
爲空,起始日期時間
後的任何一天,那麼這將是1在接下來的日子裏,直到結束日期時間或當天。
但是最後的結束日期時間必須大於或等於08:00,否則不會在當天顯示。

如果在下面的數據中顯示了參考列,以顯示行將如何顯示在輸出表中。這不會包含在輸出中。

例如的currentdate =二○一六年十一月三十零日11:00:00.000

DATA

Ref  Start      End       
1  2016-11-26 08:02:00.000 2016-11-26 09:00:00.000 
2  2016-11-27 08:00:00.000 2016-11-28 07:00:00.000 
3  2016-11-27 08:05:00.000 2016-11-28 11:00:00.000 
4  2016-11-28 07:00:00.000 2016-11-29 11:00:00.000 
5  2016-11-28 08:45:00.000 2016-11-29 06:30:00.000 
6  2016-11-25 09:00:00.000 null 

輸出

REF Date   Num 
2  2016-11-27 1 
3  2016-11-28 1 
4  2016-11-28 1 
4  2016-11-29 1 
6  2016-11-26 1 
6  2016-11-27 1 
6  2016-11-28 1 
6  2016-11-29 1 
6  2016-11-30 1 

1 and 5 are not displayed because of the criteria 

我希望這是有道理的。

預先感謝您。

回答

1

我在下面的結果中包含了所有中介計算來說明它是如何工作的。

這個想法是最初將原始時間戳移位-8小時(ShiftedStartDT,ShiftedEndDT)。

然後,您可以使用簡單的DATEDIFFDiffDays)計算它們之間的天數。

您需要檢查開始時間戳是否恰好在08:00,並將結果調整爲+ - 1(DiffAdjustment)。

那些從未交叉的行08:00邊界有0 DiffDays,所以它們可以在WHERE子句中被過濾掉。

樣本數據

DECLARE @T TABLE(Ref int, StartDT datetime2(0), EndDT datetime2(0)); 

INSERT INTO @T(Ref, StartDT, EndDT) VALUES 
(1, '2016-11-26 08:02:00', '2016-11-26 09:00:00'), 
(2, '2016-11-27 08:00:00', '2016-11-28 07:00:00'), 
(3, '2016-11-27 08:05:00', '2016-11-28 11:00:00'), 
(4, '2016-11-28 07:00:00', '2016-11-29 11:00:00'), 
(5, '2016-11-28 08:45:00', '2016-11-29 06:30:00'), 
(6, '2016-11-25 09:00:00', NULL); 

查詢

DECLARE @CurrentDT datetime2(0) = '2016-11-30 11:00:00'; 
SELECT 
    Ref 
    ,NewStartDT 
    ,DiffDays 
    ,StartDT 
    ,EndDT 
    ,ShiftedStartDT 
    ,ShiftedEndDT 
    ,DiffAdjustment 
FROM 
    @T 
    CROSS APPLY 
    (
     SELECT 
      DATEADD(hour, -8, StartDT) AS ShiftedStartDT 
      ,DATEADD(hour, -8, ISNULL(EndDT, @CurrentDT)) AS ShiftedEndDT 
    ) AS Shifted 
    CROSS APPLY 
    (
     SELECT 
      CASE WHEN ShiftedStartDT = CAST(ShiftedStartDT as date) 
      THEN 1 ELSE 0 END AS DiffAdjustment 
    ) AS Adj 
    CROSS APPLY 
    (
     SELECT 
      DATEDIFF(day, ShiftedStartDT, ShiftedEndDT) 
      + DiffAdjustment AS DiffDays 
    ) AS Diff 
    CROSS APPLY 
    (
     SELECT 
      DATEADD(day, 1-DiffAdjustment, CAST(ShiftedStartDT as date)) AS NewStartDT 
    ) AS NewStart 
WHERE 
    DiffDays > 0 
; 

結果

+-----+------------+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 
| Ref | NewStartDT | DiffDays |  StartDT  |  EndDT  | ShiftedStartDT | ShiftedEndDT  | DiffAdjustment | 
+-----+------------+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 
| 2 | 2016-11-27 |  1 | 2016-11-27 08:00:00 | 2016-11-28 07:00:00 | 2016-11-27 00:00:00 | 2016-11-27 23:00:00 |    1 | 
| 3 | 2016-11-28 |  1 | 2016-11-27 08:05:00 | 2016-11-28 11:00:00 | 2016-11-27 00:05:00 | 2016-11-28 03:00:00 |    0 | 
| 4 | 2016-11-28 |  2 | 2016-11-28 07:00:00 | 2016-11-29 11:00:00 | 2016-11-27 23:00:00 | 2016-11-29 03:00:00 |    0 | 
| 6 | 2016-11-26 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
+-----+------------+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 

如果您確實需要有Ref=4的2行和Ref=6的6行,您可以通過將此結果與一個數字表連接起來。

在我的數據庫中,我有一個名爲Numbers的表,它有一個int列,名爲Number,值爲1到100,000。它在許多疑問是有用的,它可以在此查詢中使用這樣的:

SELECT 
    Ref 
    ,NewStartDT 
    ,Num 
    ,DiffDays 
    ,StartDT 
    ,EndDT 
    ,ShiftedStartDT 
    ,ShiftedEndDT 
    ,DiffAdjustment 
FROM 
    @T 
    CROSS APPLY 
    (
     SELECT 
      DATEADD(hour, -8, StartDT) AS ShiftedStartDT 
      ,DATEADD(hour, -8, ISNULL(EndDT, @CurrentDT)) AS ShiftedEndDT 
    ) AS Shifted 
    CROSS APPLY 
    (
     SELECT 
      CASE WHEN ShiftedStartDT = CAST(ShiftedStartDT as date) 
      THEN 1 ELSE 0 END AS DiffAdjustment 
    ) AS Adj 
    CROSS APPLY 
    (
     SELECT 
      DATEDIFF(day, ShiftedStartDT, ShiftedEndDT) 
      + DiffAdjustment AS DiffDays 
    ) AS Diff 
    CROSS APPLY 
    (
     SELECT 
      DATEADD(day, 1-DiffAdjustment, CAST(ShiftedStartDT as date)) AS BaseStartDT 
    ) AS NewStart 
    CROSS APPLY 
    (
     SELECT 
      1 AS Num 
      ,DATEADD(day, dbo.Numbers.Number-1, BaseStartDT) AS NewStartDT 
     FROM dbo.Numbers 
     WHERE dbo.Numbers.Number <= DiffDays 
    ) AS CA 
ORDER BY Ref, NewStartDT; 

結果

+-----+------------+-----+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 
| Ref | NewStartDT | Num | DiffDays |  StartDT  |  EndDT  | ShiftedStartDT | ShiftedEndDT  | DiffAdjustment | 
+-----+------------+-----+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 
| 2 | 2016-11-27 | 1 |  1 | 2016-11-27 08:00:00 | 2016-11-28 07:00:00 | 2016-11-27 00:00:00 | 2016-11-27 23:00:00 |    1 | 
| 3 | 2016-11-28 | 1 |  1 | 2016-11-27 08:05:00 | 2016-11-28 11:00:00 | 2016-11-27 00:05:00 | 2016-11-28 03:00:00 |    0 | 
| 4 | 2016-11-28 | 1 |  2 | 2016-11-28 07:00:00 | 2016-11-29 11:00:00 | 2016-11-27 23:00:00 | 2016-11-29 03:00:00 |    0 | 
| 4 | 2016-11-29 | 1 |  2 | 2016-11-28 07:00:00 | 2016-11-29 11:00:00 | 2016-11-27 23:00:00 | 2016-11-29 03:00:00 |    0 | 
| 6 | 2016-11-26 | 1 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
| 6 | 2016-11-27 | 1 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
| 6 | 2016-11-28 | 1 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
| 6 | 2016-11-29 | 1 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
| 6 | 2016-11-30 | 1 |  5 | 2016-11-25 09:00:00 | NULL    | 2016-11-25 01:00:00 | 2016-11-30 03:00:00 |    0 | 
+-----+------------+-----+----------+---------------------+---------------------+---------------------+---------------------+----------------+ 
+0

謝謝您的回答。我會馬上看看。 – Mally

+0

太棒了。謝謝你。但正如你所說,我確實需要在每天08:00穿越一天。我已經從數據中排除了Ref,因爲我剛剛包含了這個數據以匹配輸出表 – Mally

+0

@Mally,我添加了第二個變體,它根據需要使用數字表根據「Ref」生成多行。 –