Выберите самую раннюю дату в диапазоне дат до перерыва - PullRequest
2 голосов
/ 06 марта 2019

Я пытался найти решение для получения самой последней даты начала из ряда диапазонов дат. Я нашел похожие темы в StackOverflow, а также на других веб-сайтах, но ни один из них не работал для моего конкретного сценария.

Вот два примера данных в моей базе данных:

Пример 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. Это связано с тем, что между 30.11.2014 и 01.01 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;

Но не повезло. Он всегда возвращает все диапазоны дат, которые я перечислил в примерах 1 или 2. Может кто-нибудь помочь, пожалуйста?

1 Ответ

1 голос
/ 06 марта 2019

Это кажется самым простым способом получения результата:

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;
...