오라클 SELECT 서브쿼리에서 최소값 + START WITH 가능한가요? 0 10 4,464

by hy [Oracle 기초] 오라클 서브쿼리 START WITH [2017.02.07 15:17:02]


안녕하세요 :D

 

오라클 입문자입니다.

제가 못해서 못하는건지, 아니면 안되는걸 되게하려고 하는건지 몰라 질문드립니다. 

오라클를 SELECT에서 서브쿼리 작성할때 서브쿼리안에 MIN() KEEP FROM (START WITH ~ CONNECT BY ~) 쿼리가 있으면 안되는건가요..? 

제 생각에 이론적으론 가능할것같은데.. A.CODE - ORA-00904: 부적합한 식별자 <- 라는 오류가 납니다.. 

제가 쉬운길을 돌아가려고 하는건지 잘 모르겠네요 ㅠ 

 

예)

SELECT ID, NAME, (

    SELECT MIN(PATH) KEEP(DENSE_RANK FIRST ORDER BY ROWNUM ASC) PATH

    FROM (

        SELECT ROWNUM, PATH

        FROM TEST_TABLE2 ST

        START WITH ST.CODE = A.CODE

        CONNECT BY PRIOR CODE = PARENTCODE

        ORDER BY SIBLINGS BY ORDER ASC

    ) MIN_PATH

) from TEST_TABLE A

ORDER BY ORDER ASC

 

+ 오라클 초급, 중급 서적 추천해주시면 감사하겠습니다. (_ _)

by jkson [2017.02.07 15:29:25]

TEST_TABLE의 컬럼조건이 이중 서브쿼리 안으로 침투하지 못하는 거구요.

테이블 구조 설명과 함께 해당 테이블을 어떻게 조회를 하시려고 하시는지

샘플 데이터, 결과 데이터 정도 적어주시면

더 나은 쿼리가 나오지 않을까 합니다.


by hy [2017.02.07 15:46:40]

답변 감사합니다 :D
 

=========================================

메뉴테이블

컬럼: 메뉴코드, 부모메뉴코드, 메뉴뎁스, 메뉴명, 메뉴경로

=========================================

위의 메뉴테이블 구조에서 현재는 4뎁스까지 있는 메뉴구조입니다.


1뎁스 메뉴를 모두 조회하면서, 해당 메뉴의 하위 메뉴들 중 첫번째 경로를 가져오려고 합니다.

 

예)

  1뎁스                      |      2뎁스                      |    3뎁스

회원관리(경로: NULL)  - | -  통계관리(경로: NULL) - | - 로그인통계(경로: A)

                               |                                  | - 가입통계(경로: B)

                               | - 매출관리(경로: C)

제품관리(경로: NULL)  - | - 제품등록(경로: D)

...

 

위와같은 데이터가 저장되어있을때 결과화면

-> 메뉴코드, 회원관리, 경로A

    메뉴코드, 제품관리, 경로D

             ....

 

부가적으로 관리자 계정 및 권한을 조회하고있습니다 :)


by 마농 [2017.02.07 15:45:15]

1. 에러 원인은
  - MIN() KEEP() 과 START WITH 를 함께 써서 에러가 난게 아니라
  - 서브쿼리에 메인 항목 조건은 1단계 서브쿼리만 가능합니다.
  - 2단계 아래 서브쿼리에서는 A.CODE 를 인지 못합니다.
2. 쿼리의 의미를 보면
  - 계층 전개후 첫행을 가져오는 것인데
  - 이는 1 레벨의 정보를 가져오는 것과 동일한 의미입니다.
  - 다시 말하면, 굳이 계층 전개를 할 필요가 없다는 의미이구요.


by hy [2017.02.07 15:55:48]

답변감사합니다!

질문에 추가설명이 부족했던것 같습니다 ㅠ

제가 계층전개를 했던 이유는 위에 댓글에 답글로 구조를 설명드렸는데요,

추가적으로 말씀드리자면 위의 구조에서..

-> 계층 전개상태의 정렬기준으로

회원관리의 경로를 가장 최하위의 첫번째 메뉴인 로그인 통계의 A 라는 경로를 가지고 오려고 하기 때문입니다.

( 회원관리 > 경로A(로그인 통계), 제품관리 > 경로D(제품등록))

정렬컬럼값은 있지만 현재 각 뎁스별로 정렬되고 있어서.. 

혹시 이런 상황에서도 더 좋은 방식이 있다면 답변 부탁드립니다..!


by 마농 [2017.02.07 16:00:46]
SELECT id
     , name
     , (SELECT path
          FROM test_table2 st
         WHERE path IS NOT NULL
           AND ROWNUM = 1
         START WITH st.code = a.code
         CONNECT BY PRIOR code = parentcode
         ORDER BY SIBLINGS BY order
        ) min_path
  FROM test_table a
 ORDER BY order
;

음. 테스트 안해보고 올렸네요.
역시나.. 테스트 해보니 Order Siblings By 구문 때문에 에러나네요.
이 댓글은 일단 무시해 주세요. ^^a


by jkson [2017.02.07 16:26:19]

ORDER BY 에 ORDER가 있는데 컬럼명이 정확히 뭐죠?? 첫번째 메뉴를 선택할 때 사용하는 컬럼인 것 같은데..

저도 일단 한번 올려봅니다.

SELECT A.CODE, B.LEAF 
  FROM TEST_TABLE A,
    (
    SELECT ROOT, MIN(메뉴경로) KEEP(DENSE_RANK FIRST ORDER BY ORD) LEAF
      FROM
        (
        SELECT CONNECT_BY_ROOT(CODE) ROOT, CODE, ORD, 메뉴경로
          FROM TEST_TABLE2
         WHERE CONNECT_BY_ISLEAF = 1
       CONNECT BY NOCYCLE PRIOR CODE = PARENTCODE
        )
     GROUP BY ROOT  
    ) B
WHERE A.CODE = B.ROOT

 


by hy [2017.02.07 16:53:40]

해결했습니다!
답변달아주신 jkson님, 마농님 두 분다 감사합니다!!

CONNECT_BY_~ 라는 함수가 있었군요.. 

테이블을 좀 더 보완할 수 있을것 같습니다! 감사합니다!!

먼저 답변해주신 jkson 님 답변으로 채택했습니다 (_ _)


by jkson [2017.02.07 17:17:24]

에러가 없었나요? 당황스럽...;

TEST_TABLE 테이블에 최상단 메뉴만 존재한다면 마농님 답변처럼 start with 로 최상단 지정해주시는 게 성능상 좋습니다.


by 마농 [2017.02.07 16:31:11]
SELECT a.id
     , a.name
     , b.min_path
  FROM test_table a
     , (SELECT code
             , MIN(path) KEEP(DENSE_RANK FIRST ORDER BY rn) min_path
          FROM (SELECT CONNECT_BT_ROOT(code) code
                     , ROWNUM rn
                     , path
                  FROM test_table2 
                 WHERE path IS NOT NULL
              -- WHERE CONNECT_BY_ISLEAF = 1
                 START WITH lvl = 1
                 CONNECT BY PRIOR code = parentcode
                 ORDER BY SIBLINGS BY order
                )
         GROUP BY code
        ) b
 WHERE a.code = b.code
 ORDER BY a.order ASC
;

 


by hy [2017.02.07 16:53:47]

해결했습니다!
답변달아주신 jkson님, 마농님 두 분다 감사합니다!!

CONNECT_BY_~ 라는 함수가 있었군요.. 

테이블을 좀 더 보완할 수 있을것 같습니다! 감사합니다!!

먼저 답변해주신 jkson 님 답변으로 채택했습니다 (_ _)

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