칼럼값을 3자리씩 잘라서 옆에 칼럼으로 + 한줄출력 0 6 2,135

by oratong [2013.01.29 01:33:21]


다음의 데이터가 있습니다.

적용년도
AD_YY
단계코드
STG_CD
구분코드
DIV_CD

NM
2012 1 1 여성가족부화이팅
2012 1 2 열심히살자
2012 1 3 산업체근무경력
2012 2 1 최전방근무
2012 2 2 데이터만들기
2012 2 3 살려줘라좀~!!
2012 3 1 영화제목내가살인자다
2012 3 2 아직도8개
2012 3 3 스페이스도한자리
2013 1 1 쩜도.한자리
2013 1 2 내이름은 세자리
2013 1 3 웃고살자
2013 1 4 청담동엘리스훗


해당하는 데이터에 대해서 다음과 같이 표현 하고 싶습니다.

AD_YY STG_CD NM1 NM11 NM111 NM1111 NM2 NM22 NM222 NM3 NM33 NM333 NM4 NM44 NM444
2012 1 여성가 족부화 이팅   열심히 살자   산업체 근무경      
2012 2 최전방 근무     데이터 만들기   살려줘 라좀~ !!      
2012 3 영화제 목내가 살인자 아직도 8개   스페이 스도한 자리      
2013 1 쩜도. 한자리     내이름 은 세 자리 웃고살   청담동 엘리스



1. DIV_CD가 2013년에는 4번까지 있는것 처럼 이것은 가변적으로 번호가 늘어날수도 줄어 들수도 있음.
2. NM의 값은 3자리씩 잘라서 옆 칼럼에 표현
3. 가령 : 3자리씩 잘라서  STG_CD 가 '1' 이면 1, 11,  111 식으로 늘어나며  STG_CD가 2이면 NM2, NM22, NM222 식으로 증가
4. NM의 길이는 가변적이며 NM1~NM1111.... 의 형식으로 표현
    (셈플 데이터에서는 NM1~NM1111의 칼럼수가 4개가 된것은 STG_CD : 3에 DIV_CD 1인 '영화제목내가살인자다' 때문임)
4. DIV_CD의 값이 가로폭이 되며 해당 값이 없는 칼럼의 경우는 NULL표시가 되어야 함.
5. 때문에 2012년 기준의 쿼리일 경우는 가로폭이 NM333 까지 이지만
  2013년 기준의 쿼리일 경우는 가로폭이 NM444 로 표현 되어야 함. ( DIV_CD가 9까지 있을수도 있음)

아무쪼록 고수님들의 조언을 부탁드립니다.

다음은 데이터 입니다.

SELECT '2012' AD_YY, '1' STG_CD, '1' DIV_CD, '여성가족부화이팅' NM FROM DUAL
UNION ALL SELECT '2012', '1', '2', '열심히살자' FROM DUAL
UNION ALL SELECT '2012', '1', '3', '산업체근무경력' FROM DUAL
UNION ALL SELECT '2012', '2', '1', '최전방근무' FROM DUAL
UNION ALL SELECT '2012', '2', '2', '데이터만들기' FROM DUAL
UNION ALL SELECT '2012', '2', '3', '살려줘라좀~!!' FROM DUAL
UNION ALL SELECT '2012', '2', '4', '영화제목내가살인자다' FROM DUAL
UNION ALL SELECT '2013', '3', '2', '아직도8개' FROM DUAL
UNION ALL SELECT '2013', '3', '3', '스페이스도한자리' FROM DUAL
UNION ALL SELECT '2013', '3', '5', '쩜도.한자리' FROM DUAL
UNION ALL SELECT '2013', '3', '2', '내이름은 세자리' FROM DUAL
UNION ALL SELECT '2013', '3', '3', '웃고살자' FROM DUAL
UNION ALL SELECT '2013', '3', '5', '청담동엘리스훗' FROM DUAL;

by 마농 [2013.01.29 10:29:48]
WITH t AS
(
SELECT '2012' ad_yy, '1' stg_cd, '1' div_cd, '여성가족부화이팅' nm FROM dual
UNION ALL SELECT '2012', '1', '2', '열심히살자'      FROM dual
UNION ALL SELECT '2012', '1', '3', '산업체근무경력'    FROM dual
UNION ALL SELECT '2012', '2', '1', '최전방근무'      FROM dual
UNION ALL SELECT '2012', '2', '2', '데이터만들기'     FROM dual
UNION ALL SELECT '2012', '2', '3', '살려줘라좀~!!'    FROM dual
UNION ALL SELECT '2012', '2', '4', '영화제목내가살인자다' FROM dual
UNION ALL SELECT '2013', '3', '1', '아직도8개'      FROM dual
UNION ALL SELECT '2013', '3', '2', '스페이스도한자리'   FROM dual
UNION ALL SELECT '2013', '3', '3', '쩜도.한자리'     FROM dual
UNION ALL SELECT '2013', '3', '4', '내이름은 세자리'   FROM dual
UNION ALL SELECT '2013', '3', '5', '웃고살자'       FROM dual
UNION ALL SELECT '2013', '3', '6', '청담동엘리스훗'    FROM dual
)
-- SQL은 2차원 테이블 형태의 결과를 리턴하는데.
-- 행은 데이터 수량에 따라 가변적으로 변할 수 있지만
-- 열은 데이터를 담는 틀로 고정입니다. 가변적으로 조정할 수 없습니다.
-- 가변적으로 조정하려면 SQL 문장 자체를 동적으로 구성해야 합니다.
-- 아래는 정적인 구조를 바탕으로 작성된 SQL 입니다.
-- 아래와 같은 SQL 문장 자체를 프로그램을 통해 동적으로 만들어 내셔야 합니다.
SELECT ad_yy, stg_cd
     , MIN(DECODE(div_cd||lv, '11', v)) nm1
     , MIN(DECODE(div_cd||lv, '12', v)) nm11
     , MIN(DECODE(div_cd||lv, '13', v)) nm111
     , MIN(DECODE(div_cd||lv, '14', v)) nm1111
     , MIN(DECODE(div_cd||lv, '21', v)) nm2
     , MIN(DECODE(div_cd||lv, '22', v)) nm22
     , MIN(DECODE(div_cd||lv, '23', v)) nm222
     , MIN(DECODE(div_cd||lv, '24', v)) nm2222
     , MIN(DECODE(div_cd||lv, '31', v)) nm3
     , MIN(DECODE(div_cd||lv, '32', v)) nm33
     , MIN(DECODE(div_cd||lv, '33', v)) nm333
     , MIN(DECODE(div_cd||lv, '34', v)) nm3333
     , MIN(DECODE(div_cd||lv, '41', v)) nm4
     , MIN(DECODE(div_cd||lv, '42', v)) nm44
     , MIN(DECODE(div_cd||lv, '43', v)) nm444
     , MIN(DECODE(div_cd||lv, '44', v)) nm4444
     , MIN(DECODE(div_cd||lv, '51', v)) nm5
     , MIN(DECODE(div_cd||lv, '52', v)) nm55
     , MIN(DECODE(div_cd||lv, '53', v)) nm555
     , MIN(DECODE(div_cd||lv, '54', v)) nm5555
     , MIN(DECODE(div_cd||lv, '61', v)) nm6
     , MIN(DECODE(div_cd||lv, '62', v)) nm66
     , MIN(DECODE(div_cd||lv, '63', v)) nm666
     , MIN(DECODE(div_cd||lv, '64', v)) nm6666
     , MIN(DECODE(div_cd||lv, '71', v)) nm7
     , MIN(DECODE(div_cd||lv, '72', v)) nm77
     , MIN(DECODE(div_cd||lv, '73', v)) nm777
     , MIN(DECODE(div_cd||lv, '74', v)) nm7777
     , MIN(DECODE(div_cd||lv, '81', v)) nm8
     , MIN(DECODE(div_cd||lv, '82', v)) nm88
     , MIN(DECODE(div_cd||lv, '83', v)) nm888
     , MIN(DECODE(div_cd||lv, '84', v)) nm8888
     , MIN(DECODE(div_cd||lv, '91', v)) nm9
     , MIN(DECODE(div_cd||lv, '92', v)) nm99
     , MIN(DECODE(div_cd||lv, '93', v)) nm999
     , MIN(DECODE(div_cd||lv, '94', v)) nm9999
  FROM (SELECT ad_yy, stg_cd, div_cd, lv
             , SUBSTR(nm, lv*3-2, 3) v
          FROM t
             , (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 9)
         WHERE lv <= LENGTH(nm)/3+1
        )
 GROUP BY ad_yy, stg_cd
 ORDER BY ad_yy, stg_cd
;

by oratong [2013.01.29 10:59:32]

마농님 아침부터 정말 감사드립니다.^^
항상 마농님께 도움 얻고 있습니다.. 뵐수 있는 날이 있기만을..^^

즐거운 하루 되십시요.ㅎ

by oratong [2013.01.29 16:53:49]

마농님 혹시 보시게 되면 질문이..

SELECT ad_yy, stg_cd
, MIN(DECODE(div_cd, '1', substr(nm, 1, 3), null)) nm1
, MIN(DECODE(div_cd, '1', substr(nm, 4, 3), null)) nm11
, MIN(DECODE(div_cd, '1', substr(nm, 7, 3), null)) nm111
, MIN(DECODE(div_cd, '1', substr(nm, 11, 3), null)) nm1111
, MIN(DECODE(div_cd, '2', substr(nm, 1, 3), null)) nm2
, MIN(DECODE(div_cd, '2', substr(nm, 4, 3), null)) nm22
, MIN(DECODE(div_cd, '2', substr(nm, 7, 3), null)) nm222
, MIN(DECODE(div_cd, '2', substr(nm, 11, 3), null)) nm2222
, MIN(DECODE(div_cd, '3', substr(nm, 1, 3), null)) nm3
, MIN(DECODE(div_cd, '3', substr(nm, 4, 3), null)) nm33
, MIN(DECODE(div_cd, '3', substr(nm, 7, 3), null)) nm333
, MIN(DECODE(div_cd, '3', substr(nm, 11, 3), null)) nm3333
, MIN(DECODE(div_cd, '4', substr(nm, 1, 3), null)) nm4
, MIN(DECODE(div_cd, '4', substr(nm, 4, 3), null)) nm44
, MIN(DECODE(div_cd, '4', substr(nm, 7, 3), null)) nm444
, MIN(DECODE(div_cd, '4', substr(nm, 11, 3), null)) nm4444
, MIN(DECODE(div_cd, '5', substr(nm, 1, 3), null)) nm5
, MIN(DECODE(div_cd, '5', substr(nm, 4, 3), null)) nm55
, MIN(DECODE(div_cd, '5', substr(nm, 7, 3), null)) nm555
, MIN(DECODE(div_cd, '5', substr(nm, 11, 3), null)) nm5555
, MIN(DECODE(div_cd, '6', substr(nm, 1, 3), null)) nm6
, MIN(DECODE(div_cd, '6', substr(nm, 4, 3), null)) nm66
, MIN(DECODE(div_cd, '6', substr(nm, 7, 3), null)) nm666
, MIN(DECODE(div_cd, '6', substr(nm, 11, 3), null)) nm6666
, MIN(DECODE(div_cd, '7', substr(nm, 1, 3), null)) nm7
, MIN(DECODE(div_cd, '7', substr(nm, 4, 3), null)) nm77
, MIN(DECODE(div_cd, '7', substr(nm, 7, 3), null)) nm777
, MIN(DECODE(div_cd, '7', substr(nm, 11, 3), null)) nm7777
, MIN(DECODE(div_cd, '8', substr(nm, 1, 3), null)) nm8
, MIN(DECODE(div_cd, '8', substr(nm, 4, 3), null)) nm88
, MIN(DECODE(div_cd, '8', substr(nm, 7, 3), null)) nm888
, MIN(DECODE(div_cd, '8', substr(nm, 11, 3), null)) nm8888
, MIN(DECODE(div_cd, '9', substr(nm, 1, 3), null)) nm9
, MIN(DECODE(div_cd, '9', substr(nm, 4, 3), null)) nm99
, MIN(DECODE(div_cd, '9', substr(nm, 7, 3), null)) nm999
, MIN(DECODE(div_cd, '9', substr(nm, 11, 3), null)) nm9999
  FROM t
 GROUP BY ad_yy, stg_cd
 ORDER BY ad_yy, stg_cd
;

와 사용하신
(SELECT ad_yy, stg_cd, div_cd, lv
, SUBSTR(nm, lv*3-2, 3) v
FROM t
, (SELECT LEVEL lv FROM dual CONNECT BY LEVEL <= 9)
WHERE lv <= LENGTH(nm)/3+1
)
를 사용했을 때와 어떤 부분에서 차이가 있을까요.


by 마농 [2013.01.29 17:10:37]

제 방법은 데이터를 복제해서 스트링을 나누어 하나의 컬럼에 지정한뒤 다시 컬럼으로 나누는 거구요.
위 방법은 복제 없이 substr 만으로 나눈거네요.
데이터를 복제하는 과정이 줄었으니 더 좋은 방법이라 할 수 있겠네요.


by 마농 [2013.01.29 17:25:36]

그리고 Decode 문의 ", Null" 부분은 생략하는게 깔끔할 것 같네요.


by oratong [2013.02.01 17:12:25]

항상 감사드립니다. 즐거운 주말 되세요 ^^
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입