database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 41653 게시물 읽기
No. 41653
문자 치환에 대해서 질문 드립니다.
작성자
그림자가면
작성일
2018-11-09 10:55
조회수
3,531

WITH TMP AS(

  SELECT 'PK1' AS PK, 'AAA #SEQ1 BBB #SEQ2' AS STR FROM DUAL UNION ALL

  SELECT 'PK2' AS PK, 'CCC #SEQ1 DDD #SEQ2' AS STR FROM DUAL

 

) , TMP1 AS (

  SELECT 'PK1' AS PK, 'SEQ1' AS SEQ, '변경1' AS COMMENT FROM DUAL UNION ALL

  SELECT 'PK1' AS PK, 'SEQ2' AS SEQ, '변경2' AS COMMENT FROM DUAL UNION ALL

  SELECT 'PK2' AS PK, 'SEQ1' AS SEQ, '변경3' AS COMMENT FROM DUAL UNION ALL

  SELECT 'PK2' AS PK, 'SEQ2' AS SEQ, '변경4' AS COMMENT FROM DUAL

)

SELECT A.PK, MAX(A.STR) AS STR

FROM TMP A, TMP1 B

WHERE 1 = 1

AND A.PK, B.PK

GROUP BY A.PK;

 

이 쿼리를 돌리면 

PK1    AAA #SEQ1 BBB #SEQ2

PK2    CCC #SEQ1 DDD #SEQ2

이렇게 결과값이 떨어집니다.

 

제가 하고 싶은건 #SEQ1, #SEQ2 이렇게 되어 있는 부분을

TMP1테이블의 SEQ필드와 일치 하는 '변경1', '변경2'값으로 값을 치환 하고 싶습니다.

PK1  AAA 변경1 BBB 변경2

PK2  CCC 변경3 DDD 변경4

이런식으로 결과를 뽑고 싶습니다.

#SEQ 값들은 동적이고 10개 이상 많아 질수도 있습니다.

 

동적으로 치환을 하려고 하는대 몇일을 고민을 해도 도저히 모르겠내요 ㅠㅠ

고수 님들의 도움좀 기다리겠습니다.

감사 합니다. 즐거운 하루 되세요.

이 글에 대한 댓글이 총 6건 있습니다.

반복 실행을 해야 해서 TMP1을 fg_rulez로 변경했습니다.

임시테이블 q를 활용해 반복 replace 를 실행하고

최종적으로 모두 바뀐 문자열만 리턴하도록

조건절을 주었습니다.

WITH TMP AS(
  SELECT 'PK1' AS PK, 'AAA #SEQ1 BBB #SEQ2 EEE #SEQ3' AS STR FROM DUAL UNION ALL
  SELECT 'PK2' AS PK, 'CCC #SEQ1 DDD #SEQ2' AS STR FROM DUAL
 
) , TMP1 AS (
  SELECT 'PK1' AS PK, 'SEQ1' AS SEQ, '변경1' AS COMENT FROM DUAL UNION ALL
  SELECT 'PK1' AS PK, 'SEQ2' AS SEQ, '변경2' AS COMENT FROM DUAL UNION ALL
  SELECT 'PK1' AS PK, 'SEQ3' AS SEQ, '변경5' AS COMENT FROM DUAL UNION ALL
  SELECT 'PK2' AS PK, 'SEQ1' AS SEQ, '변경3' AS COMENT FROM DUAL UNION ALL
  SELECT 'PK2' AS PK, 'SEQ2' AS SEQ, '변경4' AS COMENT FROM DUAL
)
, fg_rulez AS (
    SELECT PK, SEQ, COMENT, ROW_NUMBER() OVER(PARTITION BY PK ORDER BY SEQ) r
    FROM TMP1
)
, q(PK, STR, r) AS (
    SELECT PK, STR, 0 r
    FROM TMP
    UNION ALL
    SELECT fg_rulez.pk, replace(q.str, '#'||seq, coment), fg_rulez.r
    FROM q
    JOIN fg_rulez
        ON fg_rulez.PK=q.PK 
        AND q.r=fg_rulez.r-1
)
SELECT pk, str 
FROM q    
WHERE (q.pk, q.r) IN (SELECT pk, max(r) FROM   fg_rulez GROUP BY pk)  
ORDER BY pk
박인호(paerae)님이 2018-11-12 10:33에 작성한 댓글입니다.

답변 정말로 너무 감사 드립니다.

아직 모르는게 너무 많내요 ㅠㅠ

근대 정말 궁금해서 그러는대요 

Q(PK, STR, R) <== 이부분이 어떻게 동작 하는건가요?

한참을 봐도 이부분이 이해가 안되서요 

 

 

  SELECT '11' AS PK, 'AA' AS STR FROM DUAL UNION ALL

  SELECT '22' AS PK, 'BB' AS STR FROM DUAL

), Q(PK, STR) AS (

  SELECT Q.PK

       , Q.STR

  FROM Q

) SELECT PK FROM Q;

이런식으로 테스트 해봤는대 계속 에러만 나더라구요 ㅠㅠ

어떻게 동작하는건지 좀 알려주실수 있으실까요?

 

그림자가면님이 2018-11-12 14:37에 작성한 댓글입니다.
이 댓글은 2018-11-12 14:39에 마지막으로 수정되었습니다. Edit

저도 물리적인 동작원리는 알지 못합니다.

 

재귀호출 되기 위해서 q에 컬럼명을 나열해야 하고요. : q(pk, str, r) 이렇게

tmp 테이블로 q 에 데이터가 생성되고

union all 부분에서

재귀호출되면서 q에 데이터가 더 쌓입니다.

그림자가면님처럼 하면 아무 데이터가 없어 재귀호출은 할수 없습니다.

 

제일 밑에 조회쿼리에서

where문을 생략하고 보시면

데이터가 어떻게 쌓였는지 확인 가능합니다.

박인호(paerae)님이 2018-11-12 17:54에 작성한 댓글입니다.
이 댓글은 2018-11-12 18:00에 마지막으로 수정되었습니다.

답변 감사 드립니다.

공부좀 열심히 해야 겠다는 마음이 절실히 생기내요

즐거운 하루 잘 마무리 하세요^^

그림자가면님이 2018-11-12 18:02에 작성한 댓글입니다. Edit

#SEQ1 과 같은 형태에서 순번이 1자리 이상 넘어가는 경우가 있는지 확인하세요.
#SEQ10 이 존재할 경우 #SEQ1 을 Replace 할 때 #SEQ10 도 함게 바뀌는 오류가 나게 됩니다.
오류를 보정하려면 뒤에 공백까지 포함해서 확인해야 합니다.

 

WITH tmp AS
(
SELECT 'PK1' pk, 'AAA #SEQ1 BBB #SEQ2' str FROM dual
UNION ALL SELECT 'PK2', 'CCC #SEQ1 DDD #SEQ2' FROM dual
UNION ALL SELECT 'PK3', 'CCC #SEQ1 DDD #SEQ10' FROM dual
)
, tmp1 AS
(
SELECT 'PK1' pk, 'SEQ1' seq, '변경1' comments FROM dual
UNION ALL SELECT 'PK1', 'SEQ2', '변경2' FROM dual
UNION ALL SELECT 'PK2', 'SEQ1', '변경3' FROM dual
UNION ALL SELECT 'PK2', 'SEQ2', '변경4' FROM dual
UNION ALL SELECT 'PK3', 'SEQ1', '변경5' FROM dual
UNION ALL SELECT 'PK3', 'SEQ10', '변경6' FROM dual
)
, tmp2 AS
(
SELECT pk
     , '#'||seq||' ' seq
     , comments||' ' cmt
     , ROW_NUMBER() OVER(PARTITION BY pk ORDER BY seq) rn
     , COUNT(*) OVER(PARTITION BY pk) cnt
  FROM tmp1
)
, tmp3(pk, str, rn, cnt) AS
(
SELECT pk
     , str||' ' str
     , 0 rn
     , 1 cnt
  FROM tmp
 UNION ALL
SELECT b.pk
     , REPLACE(a.str, b.seq, b.cmt) str
     , b.rn
     , b.cnt
  FROM tmp3 a
     , tmp2 b
 WHERE a.pk = b.pk
   AND a.rn + 1 = b.rn
)
SELECT pk
     , RTRIM(str) str
  FROM tmp3
 WHERE rn = cnt
;

마농(manon94)님이 2018-11-12 18:18에 작성한 댓글입니다.
이 댓글은 2018-11-12 18:19에 마지막으로 수정되었습니다.

 아~ 마농님 정말 감사 합니다.

1하고 10이 겹칠수 있다는걸 생각 못했내요 

날카로운 지적 정말로 감사 드립니다.

그림자가면님이 2018-11-12 19:32에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
41656인덱스 관련해서 질문 드립니다. [2]
권기혁
2018-11-14
3191
41655오라클 쿼리 질문있습니다 [1]
JKK
2018-11-14
3416
41654주차 구하는 방법 문의 [4]
이민우
2018-11-13
3648
41653문자 치환에 대해서 질문 드립니다. [6]
그림자가면
2018-11-09
3531
41652합계 구하는 쿼리 질문 입니다. [2]
구휘
2018-11-08
4160
41651데이터베이스 일대일 관계 릴레이션 변환 질문합니다. [1]
SYJ
2018-11-04
3420
41650컬럼에서 불러온 계산식 그대로 계산하는법이 있나요? [3]
장만수
2018-11-04
3730
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.026초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다