簡體   English   中英

SQL 2012 比較多行的日期

[英]SQL 2012 Compare dates across several rows

我有一個問題,我需要比較幾行的日期。 要求是數據需要按“區域/區域”組合進行分組,最低的“開始日期”和最高的“結束日期”除非前一個“結束日期”和下一個“開始日期”之間存在超過 1 天的間隔。

“StartDate”將始終是該月的第一天,而“EndDate”將始終是該月的最后一天。

給定一個簡化的表格:

Region | Area |   StartDate   |   EndDate
-------|------|---------------|-------------
   A   |   1  |   01/01/2016  |  03/31/2016
   A   |   1  |   04/01/2016  |  05/31/2016
   A   |   1  |   07/01/2016  |  09/30/2016
   A   |   1  |   10/01/2016  |  01/31/2017
   A   |   1  |   02/01/2017  |  12/31/2017
   B   |   2  |   01/01/2016  |  04/30/2016
   B   |   2  |   05/01/2016  |  09/30/2016
   A   |   4  |   01/01/2016  |  05/31/2016
   A   |   4  |   06/01/2016  |  12/31/2016

我需要結果看起來像這樣:

Region | Area |   StartDate  |  EndDate  
-------|------|--------------|-----------
   A   |   1  |  01/01/2016  |  05/31/2016
   A   |   1  |  07/01/2016  |  12/31/2017
   B   |   2  |  01/01/2016  |  09/30/2016
   A   |   4  |  01/01/2016  |  12/31/2016

我已經嘗試過 GROUP BY 和 MIN 和 MAX 日期,但我似乎無法理解它的邏輯是正確的。

任何想法或建議將不勝感激。

這似乎是一個數據島問題。 您可以利用 SQL Server 2012 中引入的窗口函數。使用LAG窗口函數,您可以確定您的最后一條記錄結束日期時間與當前記錄開始日期時間的差距是否大於一天。 接下來,您可以使用SUM OVER子句為每個數據島生成分組 ID。

DECLARE @SourceData TABLE
(
     Region         NVARCHAR(10)
    ,Area           INT
    ,StartDate      DATETIME
    ,EndDate        DATETIME
);

INSERT INTO @SourceData
VALUES
('A', 1, '01/01/2016', '03/31/2016'),
('A', 1, '04/01/2016', '05/31/2016'),
('A', 1, '07/01/2016', '09/30/2016'),
('A', 1, '10/01/2016', '01/31/2017'),
('A', 1, '02/01/2017', '12/31/2017'),
('B', 2, '01/01/2016', '04/30/2016'),
('B', 2, '05/01/2016', '09/30/2016'),
('A', 4, '01/01/2016', '05/31/2016'),
('A', 4, '06/01/2016', '12/31/2016');

;WITH CTE_DataIslands  -- First CTE determine the start of each new data island
AS
(
    SELECT           Region
                    ,Area
                    ,StartDate
                    ,EndDate
                    ,(
                        CASE
                            WHEN DATEADD(DAY, 1, LAG(EndDate, 1) OVER  (PARTITION BY Region, Area ORDER BY StartDate ASC)) < (StartDate) THEN 1 -- If prev record's end date + 1 day  is not equal to current record's start date then it is the start of a new data island.
                            ELSE 0
                        END
                     ) AS [IsNewDataIsland]
    FROM            @SourceData 
)
, CTE_GenerateGroupingID
AS
(
    SELECT  Region
            ,Area
            ,StartDate
            ,EndDate
            ,SUM([IsNewDataIsland]) OVER (PARTITION BY Region, Area ORDER BY StartDate ASC ROWS UNBOUNDED PRECEDING) AS GroupingID  -- Create a running total of the IsNewDataIsland column this will create a grouping id we can now group on
    FROM    CTE_DataIslands
)
SELECT      Region  
            ,Area
            ,MIN(StartDate) AS StartDate
            ,MAX(EndDate) AS StartDate
FROM        CTE_GenerateGroupingID
GROUP BY    Region, Area, GroupingID

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM