🤪Я посмотрела ваши варианты, планы запросов. В целом, интересные идеи, но выглядят немножко громоздкими, и мне пришлось посидеть, подумать, позапускать частями, чтобы понять, что происходит внутри. В плане читаемости сложновато.
Я предлагаю такое решение:
SELECT
event_type,
date AS date_start,
LEAD(date) OVER(ORDER BY date) AS date_end
FROM (
SELECT
event_type,
date,
LAG(event_type, 1, -1) OVER(ORDER BY date) AS prev_event_type
FROM events) t
WHERE event_type != prev_event_type;
Что происходит?
1️⃣ Подтягиваем предыдущий тип события с офсетом и значением по умолчанию.
LAG - предыдущий элемент, LEAD - последующий.offset = 1 - берем предыдущий элемент, c 2 был бы предпредыдущий и т.д.default_value = -1 - применится для самой первой строки, т.к. еще не с чем сравнивать. Отрицательные события вряд ли будут, поэтому значение кажется безопасным для любой выборки.2️⃣ Оставляем только те строки, где текущее событие не равно предыдущему.
После этого этапа в данных лежит:
event_type date prev_event_type
1 2024-01-01 -1
2 2024-01-05 1
1 2024-01-08 2
...
3️⃣ Остается только подтянуть следующую дату по порядку.
Готово!👍