Вы можете использовать рекурсивный CTE здесь.В качестве привязки получите все существующие строки вместе с их номером, упорядоченным по метке времени на пациента.Затем выберите строку из привязки, применяя к ним следующее событие - через номер строки и пациента - и убедитесь, что следующая минута меньше метки времени последующего события.
WITH cte
AS
(
SELECT x.patient_id,
x.event_time,
x.event_status_name,
x.rn
FROM (SELECT t.patient_id,
t.event_time,
t.event_status_name,
row_number() OVER (PARTITION BY t.patient_id
ORDER BY t.event_time) rn
FROM elbat t) x
UNION ALL
SELECT c.patient_id,
dateadd(minute, 1, c.event_time),
c.event_status_name,
c.rn
FROM cte c
CROSS APPLY (SELECT y.patient_id,
y.event_time
FROM (SELECT t.patient_id,
t.event_time,
row_number() OVER (PARTITION BY t.patient_id
ORDER BY t.event_time) rn
FROM elbat t) y
WHERE y.rn = c.rn + 1) x
WHERE x.patient_id = c.patient_id
AND x.event_time > dateadd(minute, 1, c.event_time)
)
SELECT *
FROM cte c
ORDER BY c.patient_id,
c.event_time
OPTION (MAXRECURSION 1364);
Существуетхотя одна проблема.Ваши пробелы настолько велики, что максимальный уровень рекурсии в 100 превышен.Вы можете увеличить его, используя OPTION (MAXRECURSION n)
.Чтобы найти подходящий n
, вы можете запросить данные, чтобы найти максимальную разницу последующих событий в минутах.Опять же это использует row_number()
для отображения последующих событий.Возьмите этот максимум минус единицу для максимального уровня рекурсии.
WITH cte
AS
(
SELECT t.patient_id,
t.event_time,
row_number() OVER (PARTITION BY t.patient_id
ORDER BY event_time) rn
FROM elbat t
)
SELECT max(datediff(minute, c2.event_time, c1.event_time)) - 1
FROM cte c1
INNER JOIN cte c2
ON c2.patient_id = c1.patient_id
AND c2.rn = c1.rn - 1;
db <> скрипка