안녕하세요...고민하다가 의견을 구해 봅니다.
A table | B table | ||||
key | header | T/F | key | detail | |
1 | aaa | TRUE | 2 | 가 | |
2 | bbb | FALSE | 2 | 나 | |
3 | ccc | FALSE | 2 | 다 | |
4 | ddd | TRUE | 3 | 가 | |
3 | 나 | ||||
3 | 다 | ||||
3 | 라 | ||||
3 | 마 | ||||
3 | 바 | ||||
위의 두 데이블은 key로 header(A 테이블) ,detail(B 테이블) 구조를 이룹니다.
A 테이블에 T/F칼럼의 값이 FALSE 일때만 B 테이블의 데이타가 들어갑니다.(TRUE 일때는 데이타 없음)
아래의 데이타 추출 방법이 A 테이블의 T/F 칼럼의 값에 따라 detail 과 관계를 고려해서,
T/F 칼럼 값이 TRUE이면 Key에 대하여 한줄만 header 칼럼값만 뿌려주고,
T/F칼럼 값이 TRUE 처럼 한 ROW를 뿌려 주고,
FALSE에 관련된 detail 항목 값을 한 Row에 묶어서 보여주는것입니다.
그런데 False일때 Detail항목이 3개 이하면 그대로 보여주지만 3개 이상이 되면 3개를 묶어서 보여주고 .
ccc[가,나,다 외] 식으로 보여주는것입니다.
아래 추출 데이타 식으로 나타낼수 있을까요?
추출 데이터 | |||
no | key | Header Name | 분류 |
1 | 1 | aaa | TRUE |
2 | 2 | bbb | TRUE |
3 | 2 | bbb[가,나,다] | FALSE |
4 | 3 | ccc | TRUE |
5 | 3 | ccc[가,나,다 외] | FALSE |
6 | 4 | ddd | TRUE |
select ---
from ( select 1 as key , 'aaa' as header , 'TRUE' as "T/F" from dual
union all select 2 as key , 'bbb' as header , 'FALSE' as "T/F" from dual
union all select 3 as key , 'ccc' as header , 'FALSE' as "T/F" from dual
union all select 4 as key , 'ddd' as header , 'TRUE' as "T/F" from dual) A,
( select 2 as key , '가' as detail from dual
union all select 2 as key , '나' as detail from dual
union all select 2 as key , '가' as detail from dual
union all select 2 as key , '나' as detail from dual
union all select 2 as key , '다' as detail from dual
union all select 2 as key , '라' as detail from dual
union all select 2 as key , '마' as detail from dual) B
고수들의 조언을 바랍니다...즐거운 하루 되세용^^
여긴 오라클이 안되서.. 대충 쓰면
SELECT KEY , HEADER_NAME , 1 SEQ FROM A
UNION ALL
SELECT
KEY ,
'['|| (SELECT HEADER_NAME FROM A WHERE A.KEY = B1.KEY) ||WN_CONCAT(DETAIL) || CASE WHEN MAX(CNT)>3 THEN ' 외' ) || ']' HEADER _NAME ,
2 SEQ
FROM
(SELECT KEY , DETAIL
, ROW_NUMBER() OVER(PARTITION BY KEY ORDER BY DETAIL) RN
, COUNT(*) OVER(PARTITION BY KEY ) CNT FROM B ) B1
WHERE RN <= 3
GROUP BY KEY
ORDER BY KEY , SEQ
WITH a AS ( SELECT 1 key, 'aaa' header, 'TRUE' "T/F" FROM dual UNION ALL SELECT 2, 'bbb', 'FALSE' FROM dual UNION ALL SELECT 3, 'ccc', 'FALSE' FROM dual UNION ALL SELECT 4, 'ddd', 'TRUE' FROM dual ) , b AS ( SELECT 2 key, '가' detail FROM dual UNION ALL SELECT 2, '나' FROM dual UNION ALL SELECT 2, '다' FROM dual UNION ALL SELECT 3, '가' FROM dual UNION ALL SELECT 3, '나' FROM dual UNION ALL SELECT 3, '다' FROM dual UNION ALL SELECT 3, '라' FROM dual UNION ALL SELECT 3, '마' FROM dual UNION ALL SELECT 3, '바' FROM dual ) SELECT ROW_NUMBER() OVER(ORDER BY a.key, a."T/F" DESC) no , a.key , a.header||b.x header_name , a."T/F" FROM (SELECT key, header , DECODE(lv, 2, 'TRUE', "T/F") "T/F" FROM a , (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 2) WHERE lv <= DECODE("T/F", 'TRUE', 1, 2) ) a , (SELECT key , 'FALSE' "T/F" , '['||REGEXP_REPLACE( LISTAGG(detail, ',') WITHIN GROUP(ORDER BY detail) , '([^,]+,[^,]+,[^,]+),(.+)', '\1 외')||']' x FROM b GROUP BY key ) b WHERE a.key = b.key (+) AND a."T/F" = b."T/F"(+) ;
-------------- 변경전 ------------------------------------------------- -- , '['||REGEXP_REPLACE( -- LISTAGG(detail, ',') WITHIN GROUP(ORDER BY detail) -- , '([^,]+,[^,]+,[^,]+),(.+)', '\1 외')||']' x -------------- 변경후1 ------------------------------------------------ , '['||REGEXP_REPLACE( LISTAGG(detail, ',') WITHIN GROUP(ORDER BY detail) , '([^,]+)(,[^,]+){2,},([^,]+)', '\1 ~ \3')||']' x -------------- 변경후2 ------------------------------------------------ , '['|| CASE WHEN COUNT(*) <= 3 THEN LISTAGG(detail, ',') WITHIN GROUP(ORDER BY detail) ELSE MIN(detail) ||' ~ '||MAX(detail) END||']' x -- x 를 가져오는 부분만 수정하시면 되겠습니다. ------------------------