Рекурсивно перебрать таблицу SQL и найти интервалы на основе начальной и конечной дат - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть таблица SQL, которая содержит employeeid, StartDateTime и EndDatetime следующим образом:

CREATE TABLE Sample
(
    SNO INT,
    EmployeeID NVARCHAR(10),
    StartDateTime DATE,
    EndDateTime DATE
)

INSERT INTO Sample
VALUES
( 1, 'xyz', '2018-01-01', '2018-01-02' ), 
( 2, 'xyz', '2018-01-03', '2018-01-05' ), 
( 3, 'xyz', '2018-01-06', '2018-02-01' ), 
( 4, 'xyz', '2018-02-15', '2018-03-15' ), 
( 5, 'xyz', '2018-03-16', '2018-03-19' ),
( 6, 'abc', '2018-01-16', '2018-02-25' ),
( 7, 'abc', '2018-03-08', '2018-03-19' ),
( 8, 'abc', '2018-02-26', '2018-03-01' )

Я хочу, чтобы результат отображался как

EmployeeID  |  StartDateTime  |  EndDateTime
------------+-----------------+---------------
   xyz      |  2018-01-01     |  2018-02-01
   xyz      |  2018-02-15     |  2018-03-19
   abc      |  2018-01-16     |  2018-03-01
   abc      |  2018-03-08     |  2018-03-19

По сути, я хочу рекурсивнопросмотреть записи о каждом сотруднике, определить дату непрерывности начальных и конечных дат и создать набор непрерывных записей о дате.

Я написал свой запрос следующим образом:

SELECT * 
FROM dbo.TestTable T1 
LEFT JOIN dbo.TestTable t2 ON t2.EmpId = T1.EmpId
WHERE t1.EndDate = DATEADD(DAY, -1, T2.startdate)

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

Кроме того, есть случай, когда может быть несколько записей о сотрудниках, поэтому мне нужно руководство по эффективномуспособ получить желаемый результат.

Любая помощь с благодарностью.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Вы можете использовать это.

WITH T AS (
    SELECT  S1.SNO, 
            S1.EmployeeID, 
            S1.StartDateTime, 
            ISNULL(S2.EndDateTime, S1.EndDateTime) EndDateTime,
            ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId ORDER BY S1.StartDateTime) 
                - ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId, CASE WHEN S2.StartDateTime IS NULL THEN 0 ELSE 1 END  ORDER BY S1.StartDateTime ) RN,
            ROW_NUMBER() OVER(PARTITION BY S1.EmployeeId, ISNULL(S2.EndDateTime, S1.EndDateTime) ORDER BY S1.EmployeeId, S1.StartDateTime) RN_END
    FROM Sample S1
        LEFT JOIN Sample S2 ON DATEADD(DAY,1,S1.EndDateTime) = S2.StartDateTime
)
SELECT EmployeeID,  MIN(StartDateTime) StartDateTime,MAX(EndDateTime) EndDateTime FROM T
WHERE RN_END = 1
GROUP BY EmployeeID, RN
ORDER BY EmployeeID DESC, StartDateTime

Результат:

EmployeeID StartDateTime EndDateTime
---------- ------------- -----------
xyz        2018-01-01    2018-02-01
xyz        2018-02-15    2018-03-19
abc        2018-01-16    2018-03-01
abc        2018-03-08    2018-03-19
0 голосов
/ 21 сентября 2018

Это сделает это за вас.Используйте рекурсивный CTE для получения всех смежных строк, затем получите максимальную дату окончания для каждой даты начала, затем первую дату начала для каждой даты окончания.

;with cte as (
    select EmployeeID, StartDateTime, EndDateTime 
    from sample s
    union all
    select CTE.EmployeeID, CTE.StartDateTime, s.EndDateTime
    from sample s
    join cte on cte.EmployeeID=s.EmployeeID and s.StartDateTime=dateadd(d,1,CTE.EndDateTime)
)
select EmployeeID, Min(StartDateTime) as StartDateTime, EndDateTime from (
    select EmployeeID, StartDateTime, Max(EndDateTime) as EndDateTime from cte
    group by EmployeeID, StartDateTime
) q group by EmployeeID, EndDateTime
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...