안녕하세요.
혼자 고민해보다가 해결이 되지 않아 질문 드립니다 ㅠ.ㅠ
상황을 설명 드리겠습니다.
history 테이블이 하나 있다고 가정하겠습니다.
그리고 history 테이블에는 id, idx, action, regdate 정도의 컬럼이 있다고 할때..
group by id를 하게되면 id별로 그룹이 묶이게 되고
거기서 그룹핑 함수인 max,sum 등을 사용하여 데이터를 id별로 한 행씩 뽑아내는게 일반적이잖습니까..
근데 제가 지금 하고 싶은건 ㅜㅜ id별로 그룹화를 하긴하는데
그룹화해서 나온 행 중에 regdate가 최신인 행이 필요합니다..
현재 상황이 쿼리를 수정하는 방법밖에 없어서.. 해결을 해야하는데 도무지 떠오르질 않네요.
다시 상황 설명 드리자면..
id가 a인 데이터가 있다면 아래와 같이 있다면
a | 1 | 쓰기 | 20160101 |
a | 2 | 수정 | 20160526 |
a | 3 | 수정 | 20160501 |
여기서 regdate가 20160526인 저 데이터를 가져오고 싶습니다 ㅠ.ㅠ
group by a를 했는데 어떻게 해야할지..
id는 아주 많고, 각 id별로 최신 데이터를 뽑아야 합니다.
도움 부탁드리겠습니다 ㅠㅠ
WITH T AS ( SELECT 'a' id, 1 idx, '쓰기' action, '20160101' regdate FROM dual UNION ALL SELECT 'a' id, 2 idx, '수정' action, '20160526' regdate FROM dual UNION ALL SELECT 'a' id, 3 idx, '수정' action, '20160501' regdate FROM dual ) SELECT * FROM ( SELECT T.*, ROW_NUMBER() OVER(PARTITION BY T.id ORDER BY regdate desc) rn FROM T ) WHERE rn = 1
WITH T (id, idx, action, regdate) AS ( SELECT 'a' , '1' ,'쓰기' ,'20160101' FROM DUAL UNION ALL SELECT 'a' , '2' ,'수정' ,'20160526' FROM DUAL UNION ALL SELECT 'a' , '3' ,'수정' ,'20160501' FROM DUAL UNION ALL SELECT 'b' , '11' ,'쓰기2' ,'20160101' FROM DUAL UNION ALL SELECT 'b' , '22' ,'수정2' ,'20160528' FROM DUAL UNION ALL SELECT 'b' , '33' ,'수정2' ,'20160501' FROM DUAL ) SELECT MAX(T.ID) AS MAX_ID , MAX(T.IDX) KEEP (DENSE_RANK FIRST ORDER BY REGDATE DESC) MAX_IDX , MAX(T.ACTION) KEEP (DENSE_RANK FIRST ORDER BY REGDATE DESC) MAX_ACTION , MAX(T.REGDATE) KEEP (DENSE_RANK FIRST ORDER BY REGDATE DESC) MAX_REGDATE FROM T GROUP BY T.ID
row_number야 동순위에 대해 하나의 row를 가지고 오게 되지만
max keep 문은 order by 절로 sort 했을 때 중복되는 데이터가 나올 가능 성이 있으면 약간 문제가 있을 수 있어서 조심해서 사용해야해요.
SELECT 'a' , '3' ,'삭제' ,'20160526' FROM DUAL
이런 데이터가 들어갔을 때 id 'a'의 regdate '20160526'인 데이터는 두개가 되고
두개 중 max(action) '수정'이 되겠죠.
그러면 결과는
a 3 수정 20160526
b 22 수정2 20160528
실제로 idx3의 action은 '삭제'인데 '수정'이 나와버리죠.
서로 다른 row의 데이터가 뒤죽박죽이 됩니다.
중복이 생기지 않게 keep문 안의 order문을 잘 사용하셔야해요.
이 경우 idx가 높은 순으로 나와야 한다면
MAX(T.ACTION) KEEP (DENSE_RANK FIRST ORDER BY REGDATE desc, idx DESC) MAX_ACTION
이렇게 하면 되겠죠.
해서 저는 되도록 row_number를 사용합니다 ㅎ