Группировка нескольких периодов в один период - PullRequest
0 голосов
/ 24 октября 2018

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

Несколько записей идут вплотную.Значение времени окончания - это время начала следующей записи.Мне нужно объединить эти записи, чтобы сформировать один длинный период.

Я пробовал функции Lag / Lead, чтобы попытаться сгруппировать по начальному идентификатору без какого-либо успеха.

Вот скриншотданных.«IsInAGroup» - это мой производный столбец, использующий отставание / отрыв ....

SELECT ID, PeriodStart, PeriodEnd, CASE WHEN LEAD (PeriodStart) over (разделение по порядку REG_NUMBER на PeriodStart) = PeriodEnd THEN1 --ID, КОГДА LAG (PeriodEnd) закончился (разделить по порядку REG_NUMBER по PeriodStart) = PeriodStart THEN --ID 1 ELSE NULL END как «IsInAGroup» ОТ #tmpACTIVITIES ГДЕ REG_NUMBER = 'ABC123' И PeriodStart> = '6/1 /2018 'ЗАКАЗАТЬ НА 2

enter image description here

Ответы [ 2 ]

0 голосов
/ 25 октября 2018
with cte as
(
    --get all periods which don't immediately follow another period
    --these are the first record in the group (including groups of 1 record)
    --NB: assumes that a single record cannot have its PeriodStart = its own PeriodEnd
    select T1.ID, T1.START_TIME, T1.END_TIME, 1 Iteration,T1.REG_NUMBER 
    from 
        #tmpACTIVITIES T1
        LEFT JOIN #tmpACTIVITIES T2 ON (T1.REG_NUMBER=T2.REG_NUMBER) AND (T1.START_TIME=T2.END_TIME)
    WHERE 
        T2.ID IS NULL

    --where START_TIME not in (select END_TIME from #tmpACTIVITIES)

    union all

    --recursively get each period with a start date matching the last record's end date.
    --persist the original id and start date, use the new record's end date, add 1 to the iteration column each recursion
    select cte.ID, cte.START_TIME, mt.END_TIME, cte.Iteration + 1,cte.REG_NUMBER  
    from cte
    inner join #tmpACTIVITIES mt on (mt.REG_NUMBER=cte.REG_NUMBER) AND (mt.START_TIME = cte.END_TIME)
)
, cte2 as 
(
    --get all records / invert the Iteration (so the last record in a window has value r=1)
    select ID, START_TIME, END_TIME, REG_NUMBER ,row_number() over (partition by REG_NUMBER,ID order by Iteration desc) r
    from cte
)
--select all records where r=1 (i.e. the last created by the recursive cte, giving the largest range of start-to-end date for each id
select ID, START_TIME, END_TIME,REG_NUMBER 
from cte2
where r = 1
0 голосов
/ 24 октября 2018

Это бы сработало?т.е. вы просто хотите установить IsInAGroup в 1, если существует другая запись, у которой есть начальный или конечный период, соответствующий записи в конце или начальном периоде вопроса:

update a
set IsInAGroup = 1
from myTable a
where exists 
(
    select top 1 1
    from myTable b
    where b.Id != a.Id --it's a different record
    and 
    (
        b.PeriodEnd = a.PeriodStart --but the record is immediately before our record
        or b.PeriodStart = a.PeriodEnd --or the record is immediately after
    )
)

Обновление

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

with cte as
(
    --get all periods which don't immediately follow another period
    --these are the first record in the group (including groups of 1 record)
    --NB: assumes that a single record cannot have its PeriodStart = its own PeriodEnd
    select Id, PeriodStart, PeriodEnd, 1 Iteration 
    from myTable
    where PeriodStart not in (select PeriodEnd from myTable)

    union all

    --recursively get each period with a start date matching the last record's end date.
    --persist the original id and start date, use the new record's end date, add 1 to the iteration column each recursion
    select cte.Id, cte.PeriodStart, mt.PeriodEnd, cte.Iteration + 1 
    from cte
    inner join myTable mt on mt.PeriodStart = cte.PeriodEnd
)
, cte2 as 
(
    --get all records / invert the Iteration (so the last record in a window has value r=1)
    select id, PeriodStart, PeriodEnd, row_number() over (partition by id order by Iteration desc) r
    from cte
)
--select all records where r=1 (i.e. the last created by the recursive cte, giving the largest range of start-to-end date for each id
select Id, PeriodStart, PeriodEnd
from cte2
where r = 1

Надеемся, что комментарии объясняют, что происходит;но если вам нужны какие-либо разъяснения, пожалуйста, прокомментируйте.

...