by 에모토 [Oracle Tuning] REGEXP_SUBSTR [2023.02.11 08:07:56]
인터넷을 찾아보니 한 컬럼에 ,(콤마)나 |(버티컬) 등의 구분자로 묶여져 있는 값을 REGEXP_SUBSTR 함수를 사용하여 행으로 분리할 수 있다는 걸 알앗습니다. 예) COL1 값 : APPLE|ORANGE|GRAPE|BANANA SELECT REGEXP_SUBSTR(COL1, '[^|]+', 1, LEVEL) AS RSLT FROM (SELECT 'APPLE|ORANGE|GRAPE|BANANA' AS COL1 FROM DUAL) X CONNECT BY REGEXP_SUBSTR(COL1, '[^|]+', 1, LEVEL) IS NOT NULL; RSLT ---------- APPLE ORANGE GRAPE BANANA 이렇게 결과가 나오는데요... 이 쿼리문은 한 컬럼에만 적용되는 듯 하더라고요.. 제가 궁금한 것은 여러 컬럼에도 적용되는가 하는 것입니다 만약, NO, COL1, COL2, COL3 컬럼에 각각 이렇게 들어있다고 가정했을 때, NO COL1 COL2 COL3 ------------------------------------------------ 1 APPLE|BANANA ORANGE|GRAPE PEACH|KIWI 이것을 아래와 같이 나오게 쿼리문을 작성할 수 있을까요? NO COL1 COL2 COL3 ------------------------------------ 1 APPLE GRAPE KIWI 1 APPLE GRAPE PEACH 1 APPLE ORANGE KIWI 1 APPLE ORANGE PEACH 1 BANANA GRAPE KIWI 1 BANANA GRAPE PEACH 1 BANANA ORANGE KIWI 1 BANANA ORANGE PEACH 아래 쿼리는 제가 고민(?)한 끝에 만들어 본 쿼리입니다. 결과는 제대로 나오는데, 실 데이터에 적용해 보면 속도가 너무 느리네요 ㅠ 무언가 개선이 필요해 보이는데, 어떻게 접근해야 좋을지 감이 안 잡힙니다. SELECT REGEXP_SUBSTR(COL1, '[^|]+', 1, B.LV) AS RSLT1 , RSLT2 , RSLT3 FROM (SELECT COL1 , REGEXP_SUBSTR(COL2, '[^|]+', 1, B.LV) AS RSLT2 , RSLT3 FROM (SELECT COL1 , COL2 , REGEXP_SUBSTR(COL3, '[^|]+', 1, B.LV) AS RSLT3 FROM (SELECT 'APPLE|BANANA' AS COL1 , 'ORANGE|GRAPE' AS COL2 , 'PEACH|KIWI' AS COL3 FROM DUAL )X1 ,(SELECT LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= 2 )B WHERE REGEXP_SUBSTR(COL3, '[^|]+', 1, B.LV) IS NOT NULL )X2 ,(SELECT LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= 2 )B WHERE REGEXP_SUBSTR(COL2, '[^|]+', 1, B.LV) IS NOT NULL )X3 ,(SELECT LEVEL AS LV FROM DUAL CONNECT BY LEVEL <= 2 )B WHERE REGEXP_SUBSTR(COL1, '[^|]+', 1, B.LV) IS NOT NULL ORDER BY 1, 2, 3 -- 결과를 보기 좋게 하기 위해 사용하였으며 굳이 없어도 되는 부분 ;
제가 봐도 너무 절차식으로 짠 쿼리로 보이네요 ㅠ
도움주실 분에게 미리 감사의 말씀 드립니다...
WITH t AS ( SELECT 1 no, 'APPLE|BANANA' col1, 'ORANGE|GRAPE' col2, 'PEACH|KIWI' col3 FROM dual UNION ALL SELECT 2, 'APPLE|BANANA', 'ORANGE|GRAPE', 'PEACH|KIWI' FROM dual ) SELECT no , REGEXP_SUBSTR(col1, '[^|]+', 1, x) c1 , REGEXP_SUBSTR(col2, '[^|]+', 1, y) c2 , REGEXP_SUBSTR(col3, '[^|]+', 1, z) c3 FROM t , (SELECT LEVEL lv , CEIL(LEVEL / 4) x , MOD(CEIL(LEVEL / 2)-1, 2) + 1 y , MOD(LEVEL-1, 2) + 1 z FROM dual CONNECT BY LEVEL <= 8 ) ORDER BY no, lv ;
감사합니다 마농님 덕분에 잘 해결되었습니다. 우선은 실 사용 쿼리를 올리지 않은 상태로 질문을 남겨서 죄송합니다. 데이터도 그렇고 실 쿼리를 올리기 좀 그런 사정이 있어서 개념만 파악하고자 제가 만든 쿼리를 올렸습니다. 우선은 (SELECT LEVEL lv , CEIL(LEVEL / 4) x , MOD(CEIL(LEVEL / 2)-1, 2) + 1 y , MOD(LEVEL-1, 2) + 1 z FROM dual CONNECT BY LEVEL <= 8 ) 이 부분을 생각하지 못했는데, 좋은 방법을 배워갑니다. 다시 한 번 더 감사합니다^^