[英]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.