WITH T (id, time, status ) AS ( SELECT 1, '09:57', 1 FROM DUAL UNION ALL SELECT 1, '09:56', 0 FROM DUAL UNION ALL SELECT 1, '09:55', 1 FROM DUAL UNION ALL SELECT 1, '09:54', 0 FROM DUAL ) SELECT * FROM (SELECT ID , TIME , LEAD(TIME) OVER(PARTITION BY ID ORDER BY TIME DESC ) TIME2 , STATUS , ROW_NUMBER() OVER(PARTITION BY ID , STATUS ORDER BY TIME DESC ) RN FROM T ) WHERE RN = 1 AND STATUS = 0
-- scalar subquery 이용 WITH T (id, time, status ) AS ( SELECT 1, '09:57', 1 FROM DUAL UNION ALL SELECT 1, '09:56', 0 FROM DUAL UNION ALL SELECT 1, '09:55', 1 FROM DUAL UNION ALL SELECT 1, '09:54', 0 FROM DUAL ) SELECT A.* , (SELECT MAX(TIME) FROM T WHERE T.ID = A.ID AND T.STATUS = 1 AND T.TIME < A.TIME ) TIME2 FROM (SELECT ID , TIME , STATUS , ROW_NUMBER() OVER(PARTITION BY ID , STATUS ORDER BY TIME DESC ) RN FROM T ) A WHERE RN = 1 AND STATUS = 0
WITH t AS ( SELECT 1 id, '09:57' time, 1 status FROM dual UNION ALL SELECT 1, '09:56', 0 FROM dual UNION ALL SELECT 1, '09:55', 1 FROM dual UNION ALL SELECT 1, '09:54', 0 FROM dual UNION ALL SELECT 2, '09:57', 1 FROM dual UNION ALL SELECT 2, '09:56', 0 FROM dual UNION ALL SELECT 2, '09:55', 0 FROM dual UNION ALL SELECT 2, '09:54', 0 FROM dual UNION ALL SELECT 2, '09:53', 1 FROM dual UNION ALL SELECT 2, '09:52', 0 FROM dual UNION ALL SELECT 2, '09:51', 1 FROM dual ) SELECT id , s_time , e_time FROM (SELECT id, status , time e_time , LEAD(DECODE(status, 1, time)) IGNORE NULLS OVER(PARTITION BY id ORDER BY time DESC) s_time , ROW_NUMBER() OVER(PARTITION BY id, status ORDER BY time DESC) rn FROM t ) WHERE status = 0 AND rn = 1 ;
전체자료를 모두 읽는 방식인데요.
인덱스 구성에 따라 최적화 쿼리는 다른 형태로 구현될 수 있습니다.
DBMS 는 오라클인가요?
왜 질문하실 때 DBMS 를 명시하지 않을까요? 문법이 다 다른데.
포스그래에서는 IGNORE NULLS 구문이 안되므로 아찌님 방법을 사용하면 될텐데요?
뭐가 안될까요?
WITH t AS ( SELECT 1 id, '09:57' vtime, 1 status UNION ALL SELECT 1, '09:56', 0 UNION ALL SELECT 1, '09:55', 1 UNION ALL SELECT 1, '09:54', 0 UNION ALL SELECT 2, '09:57', 1 UNION ALL SELECT 2, '09:56', 0 UNION ALL SELECT 2, '09:55', 0 UNION ALL SELECT 2, '09:54', 0 UNION ALL SELECT 2, '09:53', 1 UNION ALL SELECT 2, '09:52', 0 UNION ALL SELECT 2, '09:51', 1 ) SELECT id , vtime , (SELECT MAX(b.vtime) FROM t b WHERE b.id = a.id AND b.vtime < a.vtime AND b.status = 1 ) s_time FROM (SELECT id, status , vtime , ROW_NUMBER() OVER(PARTITION BY id ORDER BY vtime DESC) rn FROM t WHERE status = 0 ) a WHERE rn = 1 ;
WITH t AS ( SELECT 1 id, '09:57' vtime, 1 status UNION ALL SELECT 1, '09:56', 0 UNION ALL SELECT 1, '09:55', 1 UNION ALL SELECT 1, '09:54', 0 UNION ALL SELECT 2, '09:57', 1 UNION ALL SELECT 2, '09:56', 0 UNION ALL SELECT 2, '09:55', 0 UNION ALL SELECT 2, '09:54', 0 UNION ALL SELECT 2, '09:53', 1 UNION ALL SELECT 2, '09:52', 0 UNION ALL SELECT 2, '09:51', 1 ) SELECT id , s_time , e_time FROM (SELECT id, status , vtime e_time , MAX(CASE status WHEN 1 THEN vtime END) OVER(PARTITION BY id ORDER BY vtime) s_time , ROW_NUMBER() OVER(PARTITION BY id, status ORDER BY vtime DESC) rn FROM t ) a WHERE status = 0 AND rn = 1 ;
완료
SELECT id, vtime s_time, e_time
FROM ( select *,(CASE status WHEN 1 THEN LEAD(vtime) OVER ( partition by id order by vtime asc ) END ) e_time
from (SELECT id, vtime, status, lag( status ) over ( order by vtime asc ) tt
FROM t
WHERE id = 2 and vtime > '09:50' and vtime < '10:00'
ORDER BY vtime asc)tmp
where (status = 1 and tt = 0) or (status = 0 and tt = 1 ) ) a
WHERE e_time is not null;