Это можно сделать немного проще. Сначала давайте создадим пример таблицы:
SQL> create table mytable (id,state,state_time)
2 as
3 select 1, 'Open', date '2009-03-02' from dual union all
4 select 1, 'Closed', date '2009-03-05' from dual union all
5 select 1, 'Open', date '2009-03-11' from dual union all
6 select 1, 'Shut down', date '2009-03-26' from dual union all
7 select 1, 'Wiped out', date '2009-03-24' from dual union all
8 select 1, 'Demolished', date '2009-04-13' from dual
9 /
Table created.
Данные равны выводу вашего оператора выбора:
SQL> SELECT id,
2 DECODE(state, 'Open', state_in, NULL) AS open_in,
3 DECODE(state, 'Not Open', state_in, NULL) AS open_out
4 FROM (
5 SELECT id,
6 CASE WHEN state = 'Open'
7 THEN 'Open'
8 ELSE 'Not Open'
9 END AS state,
10 TRUNC(state_time) AS state_in
11 FROM mytable
12 )
13 /
ID OPEN_IN OPEN_OUT
---------- ------------------- -------------------
1 02-03-2009 00:00:00
1 05-03-2009 00:00:00
1 11-03-2009 00:00:00
1 26-03-2009 00:00:00
1 24-03-2009 00:00:00
1 13-04-2009 00:00:00
6 rows selected.
А вот немного более простой запрос:
SQL> select id
2 , min(case when state = 'Open' then state_time end) open_in
3 , min(case when state != 'Open' then state_time end) open_out
4 from ( select id
5 , state
6 , state_time
7 , max(x) over (partition by id order by state_time) grp
8 from ( select id
9 , state
10 , state_time
11 , case state
12 when 'Open' then
13 row_number() over (partition by id order by state_time)
14 end x
15 from mytable
16 )
17 )
18 group by id
19 , grp
20 order by id
21 , open_in
22 /
ID OPEN_IN OPEN_OUT
---------- ------------------- -------------------
1 02-03-2009 00:00:00 05-03-2009 00:00:00
1 11-03-2009 00:00:00 24-03-2009 00:00:00
2 rows selected.
С уважением,
Роб.