오라클 계층형쿼리 질문이요. 0 8 1,726

by ekekekek [Oracle 기초] #오라클 [2018.05.28 16:45:34]


안녕하세요. 

오라클에서 계층쿼리를 사용하고 있습니다.

계층형쿼리에서 특정 a라는 값으로  검색을 하면

최상위 노드부터 a라는 값이 포함되어있는 모든 노드까지 노드별로 출력이 되도록 하고싶은데..

distinct나 union을 사용하지않고 하는 방법이 있을까요?

 

└ 2

  └  2a

       2b

└ 3

   └ 3a

       3b

형태에서 a라는 결과 검색시

└ 2

  └  2a

└ 3

  └ 3a

이런 형태의 값을 출력하고 싶습니다.

by 마농 [2018.05.28 17:02:29]

검색조건이 이퀄(=)이 아닌 LIKE 검색인가요?
a 의 하위 자식이 존재할 때 하위 자식도 나와야 하나요? a 까지만 나오면 되나요?


by ekekekek [2018.05.28 17:06:41]

LIKE를 사용중이고 하위자식까지 출력이되야됩니다.


by 마농 [2018.05.28 17:11:16]

LIKE 검색의 경우 DISTINCT 필요합니다.
하위도 나와야 한다면? UNION ALL 필요합니다.
DISTINCT 나 UNION ALL 을 다른걸로 대체할수는 있겠지만
오히려 구문만 더 복잡해 질 수도 있고, 성능만 더 나빠질 수도 있습니다.
굳이 특정 구문을 사용하지 말아야 하는 합당한 이유가 있을까요?


by ekekekek [2018.05.28 17:15:05]

사용안하고 할 수 있는 방법이 있나 찾아보고있었는데..방법이없는거군요 ㅠㅠ 감사합니다.


by 마농 [2018.05.28 17:19:52]

방법이 없다고는 하지 않았습니다.
조인이나 조건절 서브쿼리 등으로 대체가 가능할 수 있습니다.
다만 굳이 그렇게까지 해야만 하는 합당한 이유가 있는지를 생각하게 할 뿐이죠.


by ekekekek [2018.05.28 17:21:09]

요구사항이 DISTINCT나 UNION을 사용하지않고 검색을 해야될 상황이라서요.


by 마농 [2018.05.28 17:36:45]

요구사항이 그러하니 어쩔수 없다는 건가요?
저는 왜 그런 요구를 했는지 그 이유가 궁금합니다.
합당한 이유가 아니라면 설득하고 대안을 제시할 수 있어야 합니다.

WITH t AS
(
SELECT '1' cd, '' pcd FROM dual
UNION ALL SELECT '2' , '1'  FROM dual
UNION ALL SELECT '2a', '2'  FROM dual
UNION ALL SELECT '2b', '2'  FROM dual
UNION ALL SELECT '3' , '1'  FROM dual
UNION ALL SELECT '3a', '3'  FROM dual
UNION ALL SELECT '3b', '3'  FROM dual
UNION ALL SELECT '4' , '1'  FROM dual
UNION ALL SELECT '4a', '4'  FROM dual
UNION ALL SELECT '4c', '4a' FROM dual
UNION ALL SELECT '4b', '4'  FROM dual
)
-- 1. 내가 생각하는 정답(추천) --
SELECT *
  FROM (SELECT DISTINCT cd, pcd
          FROM t
         START WITH INSTR(cd, 'a') > 0
         CONNECT BY cd = PRIOR pcd
         UNION ALL
        SELECT cd, pcd
          FROM t
         START WITH INSTR(pcd, 'a') > 0
         CONNECT BY PRIOR cd = pcd
        )
 START WITH pcd IS NULL
 CONNECT BY PRIOR cd = pcd
;
-- 2. Distnct 와 Union 을 사용하지 않고 구현(비추) --
SELECT *
  FROM (SELECT *
          FROM t a
         WHERE EXISTS (SELECT 1
                         FROM t
                        WHERE INSTR(cd, 'a') > 0
                        START WITH cd = a.cd
                        CONNECT BY PRIOR cd = pcd
                       )
            OR EXISTS (SELECT 1
                         FROM t
                        WHERE INSTR(cd, 'a') > 0
                        START WITH cd = a.cd
                        CONNECT BY cd = PRIOR pcd
                       )
        )
 START WITH pcd IS NULL
 CONNECT BY PRIOR cd = pcd
;

 


by ekekekek [2018.05.28 17:47:37]

저도 1번방법을 사용하고싶지만 이제 2달넘은 신입개발자라 아직 아무것도 모르는 상황이라 어쩔수가 없었습니다....

바쁜시간내셔서 문제 해결해 주셔서 감사합니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입