РЕДАКТИРОВАТЬ SQL обновляется в соответствии с комментарием.
WITH
group_assigned_data AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY customer_status ORDER BY effective_from_date) AS status_sequence_id,
ROW_NUMBER() OVER ( ORDER BY effective_from_date) AS sequence_id,
customer_status,
effective_from_date
FROM
your_table
)
,
grouped_data AS
(
SELECT
customer_status,
MIN(effective_from_date) AS min_effective_from_date,
MAX(effective_from_date) AS max_effective_from_date
FROM
group_assigned_data
GROUP BY
customer_status,
sequence_id - status_sequence_id
)
SELECT
[current].customer_status,
[current].min_effective_from_date AS effective_from,
[next].min_effective_from_date AS effective_to
FROM
grouped_data AS [current]
LEFT JOIN
grouped_data AS [next]
ON [current].max_effective_from_date = [next].min_effective_from_date + 1
ORDER BY
[current].min_effective_from_date
Это не рекурсивно, но, возможно, это хорошо.
Это не касается пробелов в ваших данных. Чтобы справиться с этим, вы можете создать таблицу календаря с каждой соответствующей датой и присоединиться к ней, чтобы заполнить недостающие даты статусом «неизвестно», а затем выполнить запрос для этого. (На самом деле, вы говорите, что это CTE, который используется CTE выше).
В настоящее время ...
- Если строка 2 отсутствует, это не изменит результат
- Если строка 3 отсутствует, end_date первой строки изменится
Различное поведение можно определить, подготовив ваши данные или другими методами. Нам нужно знать бизнес-логику, которая вам нужна.
Если у какой-либо одной даты может быть несколько записей о статусе, вам необходимо определить, какой логике вы хотите следовать. В настоящее время поведение не определено, но вы можете исправить это, просто добавив customer_status
к ORDER BY
частям ROW_NUMBER ().