아래와 같이 데이터가 있을떄
각 행별로 중복된 숫자를 보여주는 컬럼을
쿼리로 어떻게 구현할 수 있을까요?
(아래 h열을 구성하고 싶은겁니다)
* 중복된 수가 없으면 null, 0이 중복되면 0으로 표기
a b c d e f g
---------------
6 7 8 9 0 8 3
0 5 1 5 8 3 1
2 7 9 5 9 6 6
[결과]
a b c d e f g h
-----------------
6 7 8 9 0 8 3 (8)
0 5 1 5 8 3 1 (5,1)
2 7 9 5 9 6 6 (9,6)
WITH t(a, b, c, d, e, f, g) AS ( SELECT 6, 7, 8, 9, 0, 8, 3 FROM dual UNION ALL SELECT 0, 5, 1, 5, 8, 3, 1 FROM dual UNION ALL SELECT 2, 7, 9, 5, 9, 6, 6 FROM dual ) SELECT rn , MIN(DECODE(gb, 'A', v)) a , MIN(DECODE(gb, 'B', v)) b , MIN(DECODE(gb, 'C', v)) c , MIN(DECODE(gb, 'D', v)) d , MIN(DECODE(gb, 'E', v)) e , MIN(DECODE(gb, 'F', v)) f , MIN(DECODE(gb, 'G', v)) g , LISTAGG(h, ',') WITHIN GROUP(ORDER BY gb) h FROM (SELECT rn, gb, v , DECODE(ROW_NUMBER() OVER(PARTITION BY rn, v ORDER BY gb), 2, v) h FROM (SELECT ROWNUM rn, a, b, c, d, e, f, g FROM t) UNPIVOT (v FOR gb IN (a, b, c, d, e, f, g)) ) GROUP BY rn ORDER BY rn ;
-- 간단하게는 실패... 그냥 무식하게.. WITH T ( A , B , C , D , E , F , G ) AS ( SELECT '6' , '7' , '8' , '9' , '0' , '8' , '3' FROM DUAL UNION ALL SELECT '0' , '5' , '1' , '5' , '8' , '3' , '1' FROM DUAL UNION ALL SELECT '2' , '7' , '9' , '5' , '9' , '6' , '6' FROM DUAL ), T2 AS ( SELECT GB , LN , V FROM ( SELECT ROWNUM GB , A , B , C , D ,E , F , G FROM T ) UNPIVOT ( V FOR LN IN ( A AS 1 , B AS 2 , C AS 3 , D AS 4 ,E AS 5 , F AS 6 , G AS 7 )) ) SELECT * FROM (SELECT GB , LN , V FROM T2 UNION ALL SELECT GB , 99 , LISTAGG(V,',') WITHIN GROUP(ORDER BY ST) LIST_V FROM (SELECT GB ,MIN(LN) ST, V FROM T2 GROUP BY GB , V HAVING COUNT(*) > 1) GROUP BY GB ) PIVOT ( MIN(V) FOR LN IN ( 1 A , 2 B , 3 C , 4 D , 5 E , 6 F , 7 G , 99 H )) ORDER BY GB
ROW_NUMBER() = 2 로 하면 순서가 꼬일 가능성이 있네요.(4번행 9,6 이 나와야 하는데 6,9 가 나옴)
ROW_NUMBER() = 1 AND COUNT(*) > 1 로 변경했습니다.
WITH t(a, b, c, d, e, f, g) AS ( SELECT 6, 7, 8, 9, 0, 8, 3 FROM dual UNION ALL SELECT 0, 5, 1, 5, 8, 3, 1 FROM dual UNION ALL SELECT 2, 7, 9, 5, 9, 6, 6 FROM dual UNION ALL SELECT 2, 7, 9, 6, 6, 6, 9 FROM dual ) SELECT rn , MIN(DECODE(gb, 'A', v)) a , MIN(DECODE(gb, 'B', v)) b , MIN(DECODE(gb, 'C', v)) c , MIN(DECODE(gb, 'D', v)) d , MIN(DECODE(gb, 'E', v)) e , MIN(DECODE(gb, 'F', v)) f , MIN(DECODE(gb, 'G', v)) g , LISTAGG(h, ',') WITHIN GROUP(ORDER BY gb) h FROM (SELECT rn, gb, v , CASE WHEN ROW_NUMBER() OVER(PARTITION BY rn, v ORDER BY gb) = 1 AND COUNT(*) OVER(PARTITION BY rn, v) > 1 THEN v END h FROM (SELECT ROWNUM rn, a, b, c, d, e, f, g FROM t) UNPIVOT (v FOR gb IN (a, b, c, d, e, f, g)) ) GROUP BY rn ORDER BY rn ;