Я думаю, что вам нужно условное lead()
с опцией ignore nulls
:
select
id,
date from_date,
case when status = 'ON'
then lead(case when status = 'OFF' then date end ignore nulls)
over(partition by id order by date)
end to_date,
status
from mytable
Чтобы лучше соответствовать ожидаемым результатам, мы применяем функцию к любому состоянию, отличному от 'OFF'
, и снимаем 1 день от результата:
select
id,
date from_date,
case when status <> 'OFF'
then lead(case when status = 'OFF' then date end ignore nulls)
over(partition by id order by date) - 1
end to_date,
status
from mytable
Если вам также нужна следующая 'ON'
дата для 'OFF'
строк:
select
id,
date from_date,
case when status <> 'OFF'
then lead(case when status = 'OFF' then date end ignore nulls)
over(partition by id order by date) - 1
else lead(case when status = 'ON' then date end ignore nulls)
over(partition by id order by date) - 1
end to_date,
status
from mytable
Демонстрация в DB Fiddlde
Первый запрос:
ID | FROM_DATE | TO_DATE | STATUS
----: | :-------- | :-------- | :-----
15643 | 10-MAR-20 | 20-MAR-20 | ON
15643 | 15-MAR-20 | <em>null</em> | test
15643 | 20-MAR-20 | <em>null</em> | OFF
Второй запрос:
ID | FROM_DATE | TO_DATE | STATUS
----: | :-------- | :-------- | :-----
15643 | 10-MAR-20 | 19-MAR-20 | ON
15643 | 15-MAR-20 | 19-MAR-20 | test
15643 | 20-MAR-20 | <em>null</em> | OFF
Третий запрос (вы не видите разницу со вторым запросом поскольку нет строки 'OFF'
со следующей 'ON'
):
ID | FROM_DATE | TO_DATE | STATUS
----: | :-------- | :-------- | :-----
15643 | 10-MAR-20 | 19-MAR-20 | ON
15643 | 15-MAR-20 | 19-MAR-20 | test
15643 | 20-MAR-20 | <em>null</em> | OFF