Используйте lag()
. Я думаю, что это делает то, что вы хотите:
select t.ref, t.status, t.fromDate as changedDate
from (select t.*,
lag(status) over (partition by ref order by fromDate) as prev_status,
row_number() over (partition by ref order fromDate) as seqnum
from t
) t
where prev_status <> status or
prev_status is null and status is not null or
prev_status is not null and status is null or
seqnum = 1;
Значения NULL
усложняют задачу. Последнее условие обрабатывает случай, когда первая строка для ссылки NULL
.
Я думаю, что другой подход немного проще:
select t.ref, t.status, t.fromDate as changedDate
from (select t.*,
lag(fromDate) over (partition by ref order by fromDate) as prev_date,
lag(fromDate) over (partition by ref, status order by fromDate) as prev_status_date
from t
) t
where prev_status_date is null or
prev_status_date <> prev_date;
Это просто сравнивает предыдущую дату для статус на предыдущую дату для записи в целом.