Select 中断发生前日期范围内的最早日期
Select Earliest Date Within a Range of Dates Before a Break Occurs
我一直在努力寻找一种解决方案,以从一系列日期范围中获取最近的开始日期。我在 Whosebug 和其他网站上找到了类似的主题,但 none 适合我的特定场景。
以下是我数据库中的两个数据示例:
示例 1
Start Date | End Date
-----------|-----------
8/26/2006 | 5/31/2016
6/1/2016 | 12/31/2017
1/1/2018 | NULL
对于这个例子,我希望查询的结果是:8/26/2006
。这是因为开始日期和结束日期是连续的,一直到原始开始日期。
示例 2
Start Date | End Date
-----------|-----------
7/6/2014 | 11/30/2014
1/1/2019 | NULL
对于这个例子,我希望查询的结果是:1/1/2019
。这是因为 11/30/2014 和 1/1/2019 之间有休息时间。
我不需要所有日期的列表,甚至不需要返回的结束日期。我只需要日期范围中断之前的最早开始日期。
我猜我需要的是循环遍历记录的递归 CTE,例如:
WITH CTE AS
(
SELECT
T1.StartDate
,T1.EndDate
FROM
ExampleTable AS T1
LEFT JOIN
ExampleTable AS T2
ON
T1.EmployeeID = T2.EmployeeID
AND T1.StartDate - 1 = T2.EndDate
WHERE
T1.EmployeeID = @EmployeeID
UNION ALL
SELECT
C.EmployeeID
,C.StartDate
,T2.EndDate
FROM
CTE AS C
JOIN
ExampleTable AS T2
ON
C.EmployeeID = T2.EmployeeID
AND T2.StartDate - 1 = C.EndDate
)
SELECT
StartDate
,NULLIF(MAX(ISNULL(EndDate, '32121231')), '32121231') AS EndDate
FROM
CTE
GROUP BY
StartDate;
但运气不好。它总是 returns 我在示例 1 或 2 中列出的所有日期范围。有人可以帮忙吗?
这似乎是获得结果的最简单方法:
SELECT TOP 1 StartDate
FROM YourTable
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;
因此,对于您的数据:
WITH VTE AS(
SELECT CONVERT(date, StartDate,101) AS StartDate,
CONVERT(date, EndDate,101) AS EndDate
FROM (VALUES('7/6/2014','11/30/2014'),
('1/1/2019',NULL)) V(StartDate, EndDate))
SELECT TOP 1 StartDate
FROM VTE
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;
WITH VTE AS(
SELECT CONVERT(date, StartDate,101) AS StartDate,
CONVERT(date, EndDate,101) AS EndDate
FROM (VALUES('8/26/2006','5/31/2016'),
('6/1/2016 ','12/31/2017'),
('1/1/2018 ',NULL)) V(StartDate, EndDate))
SELECT TOP 1 StartDate
FROM VTE
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;
我一直在努力寻找一种解决方案,以从一系列日期范围中获取最近的开始日期。我在 Whosebug 和其他网站上找到了类似的主题,但 none 适合我的特定场景。
以下是我数据库中的两个数据示例:
示例 1
Start Date | End Date
-----------|-----------
8/26/2006 | 5/31/2016
6/1/2016 | 12/31/2017
1/1/2018 | NULL
对于这个例子,我希望查询的结果是:8/26/2006
。这是因为开始日期和结束日期是连续的,一直到原始开始日期。
示例 2
Start Date | End Date
-----------|-----------
7/6/2014 | 11/30/2014
1/1/2019 | NULL
对于这个例子,我希望查询的结果是:1/1/2019
。这是因为 11/30/2014 和 1/1/2019 之间有休息时间。
我不需要所有日期的列表,甚至不需要返回的结束日期。我只需要日期范围中断之前的最早开始日期。
我猜我需要的是循环遍历记录的递归 CTE,例如:
WITH CTE AS
(
SELECT
T1.StartDate
,T1.EndDate
FROM
ExampleTable AS T1
LEFT JOIN
ExampleTable AS T2
ON
T1.EmployeeID = T2.EmployeeID
AND T1.StartDate - 1 = T2.EndDate
WHERE
T1.EmployeeID = @EmployeeID
UNION ALL
SELECT
C.EmployeeID
,C.StartDate
,T2.EndDate
FROM
CTE AS C
JOIN
ExampleTable AS T2
ON
C.EmployeeID = T2.EmployeeID
AND T2.StartDate - 1 = C.EndDate
)
SELECT
StartDate
,NULLIF(MAX(ISNULL(EndDate, '32121231')), '32121231') AS EndDate
FROM
CTE
GROUP BY
StartDate;
但运气不好。它总是 returns 我在示例 1 或 2 中列出的所有日期范围。有人可以帮忙吗?
这似乎是获得结果的最简单方法:
SELECT TOP 1 StartDate
FROM YourTable
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;
因此,对于您的数据:
WITH VTE AS(
SELECT CONVERT(date, StartDate,101) AS StartDate,
CONVERT(date, EndDate,101) AS EndDate
FROM (VALUES('7/6/2014','11/30/2014'),
('1/1/2019',NULL)) V(StartDate, EndDate))
SELECT TOP 1 StartDate
FROM VTE
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;
WITH VTE AS(
SELECT CONVERT(date, StartDate,101) AS StartDate,
CONVERT(date, EndDate,101) AS EndDate
FROM (VALUES('8/26/2006','5/31/2016'),
('6/1/2016 ','12/31/2017'),
('1/1/2018 ',NULL)) V(StartDate, EndDate))
SELECT TOP 1 StartDate
FROM VTE
ORDER BY CASE WHEN LAG(EndDate) OVER (ORDER BY StartDate) = DATEADD(DAY,-1,StartDate) THEN 1 ELSE 0 END,
StartDate DESC;