서브쿼리에서 이상한 현상을 설명해 주세요 0 5 2,527

by 김종만 [2008.01.18 16:29:35]


 

테이블 설명

 

PUB0900 코드 마스터

PUB0910  코드 디테일

 

기타 : 업무용 테이블

 

 

다음 쿼리에서 코드값을 가져오는 부분을 이해할 수 없습니다.(빨간색)

 

SELECT A.* FROM (
SELECT A.*, LEAD(STATUS, 1, 0) OVER(ORDER BY PR_NO, PO_REV DESC) AS BEFORE_STATUS FROM (
 SELECT
             A.PURREQ_NO,
             A.PURREQ_TITLE,
             A.PURREQ_ID,
             (SELECT MAX(USER_NAME_K) FROM PUB0130V WHERE ACCT_ID = A.PUR_CHARGE) AS PUR_CHARGE,
             (SELECT MAX(USER_NAME_K) FROM PUB0130V WHERE ACCT_ID = A.SUPT_CHARGE) AS SUPT_CHARGE,
             (SELECT MAX(USER_NAME_K) FROM PUB0130V WHERE ACCT_ID = A.SPOT_CHARGE) AS SPOT_CHARGE,
             A.REQ_DATE,
             SUBSTR(A.DEL_START,0,4) || '-' || SUBSTR(A.DEL_START,5,2) || '-' || SUBSTR(A.DEL_START,7,2) || ' ~ '|| SUBSTR(A.DEL_END,0,4) || '-'
 || SUBSTR
  (A.DEL_END,5,2) || '-' || SUBSTR(A.DEL_END,7,2)  DEL_DATE ,
             A.STATUS,
             A.PURREQ_ID AS  PURREQ_ID2,
             ( SELECT CODE_NAME_KOR
                  FROM PUB0910T
                  WHERE COMM_CODE_ID = (SELECT COMM_CODE_ID
                                                FROM PUB0900T
                                                WHERE COMM_CODE = 'PUR_PR_STATUS'

                                                AND CODE = A.STATUS) ) AS STATUS2,
             (SELECT COUNT(*) CNT FROM PUR1060T WHERE PURREQ_ID= A.PURREQ_ID  )  ITEM_COUNT
             , A.PR_NO, A.DEPT_CD, A.PO_REV
 FROM PUR1050T A
      ,(
  SELECT RFQ_ID, RFQ_STAT, DEPT_CD, PR_NO
  FROM PUR3000T
  WHERE RFQ_ID IN (
             SELECT
                  MAX(RFQ_ID) RFQ_ID
             FROM PUR3000T
             WHERE (DEPT_CD, PR_NO) IN (
                   SELECT
                         DEPT_CD, PR_NO
                   FROM PUR1050T
                   WHERE 1=1
                     AND PR_NO IS NOT NULL
                   GROUP BY DEPT_CD, PR_NO
                   HAVING COUNT(*) > 1
                   )
             GROUP BY DEPT_CD, PR_NO
          )
      ) B
 WHERE A.DEPT_CD = B.DEPT_CD
   AND A.PR_NO = B.PR_NO
   AND NOT EXISTS (
             SELECT '1'
             FROM PUR5000T C
             WHERE C.RFQ_ID = B.RFQ_ID
      )
 ) A
 ) A
 WHERE 1=1
   AND A.PO_REV > 0
   ORDER BY PURREQ_NO DESC
;

근데 PUB0900에는 CODE란 필드가 없습니다. 에러가 나야 되는 건 아닌가요?

 

이렇게 되어야 하는데

 

             ( SELECT CODE_NAME_KOR
                  FROM PUB0910T
                  WHERE COMM_CODE_ID = (SELECT COMM_CODE_ID
                                                FROM PUB0900T
                                                WHERE COMM_CODE = 'PUR_PR_STATUS'

                                               ) AND CODE = A.STATUS) AS STATUS2,

 

 

결과는 똑같습니다.

 

왜 그런지 이유를 설명해 주실 분?

 

참고로 오라클 9i 입니다.

 

 

 

by 나그네 [2008.01.18 00:00:00]
PUB0910T 테이블의 code 컬럼을 조건으로 사용한것 뿐입니다. PUB0910T 도 없다면 그건 에러겠지요.
알리어스를 줘보세요. 그럼더 명확해 지겠지요..

by 김종만 [2008.01.18 00:00:00]
나그네님/

pub0910T의 code 컬럼을 조건으로 사용한 것같은데 (SELECT COMM_CODE_ID .... AND CODE = A.STATUS) 을 연산순서를 볼때 COMM_CODE_ID값을 가져오는 것 아닌가요? 그런데, PUB0900T에 CODE컬럼이 없다는 거죠. 얼리어스를 올리라는 건 테이블 디스크립션을 말하는 건가요?

by 마농 [2008.01.20 00:00:00]
아마도 쿼리 파싱과정에서 code 항목을 900t 테이블에서 참조하려고 시도했다가 없는것을 확인한 후 다시 910t 테이블에서 참조한것 같습니다.
이러한 의도되지 않는 방향으로 나가는것을 방지하기 위해서라도 컬럼명을 기술할때는 반드시 테이블명.컬럼명 으로 기술해서 사용해야겠지요.
테이블 알리아스를 사용했다면 알리아스명.컬럼명으로 사용되야 하겠지요.
WHERE PUB0910T.code = a.status
테이블간 조인시에는 알리아스를 사용하시고 컬럼명은 반드시 알리아스.컬럼명으로 사용하셔야지만 오해의 소지가 없어지겠죠.
알리아스 안달아두시면 나중에 다른사람이 쿼리 고칠때 난감합니다.

by 김종만 [2008.01.21 00:00:00]
마농님/

답변 고맙습니다.
테이블 조인에 관한 조언도요. 파싱과정에서 900t 테이블에서 참조하려고 시도했다가 없는 것을 확인한 후 910t를 참조한 것 같다는 것에 동감합니다. 그렇다면 이것도 일종의 버그라고 볼 수 있나요? 옵티마이저의 파싱과정에 대한 참고할 만한 문서나 서적이 있으면 추천 좀 해 주시죠?

by 마농 [2008.01.21 00:00:00]
버그라기 보다는 테이블명을 기술해주지 않은 컬럼의 테이블 정보를 찾아가는 일종의 규칙이라고 생각되네요.
물론 제 개인적인 생각입니다.
관련 문서나 서적은 다른분께서 추천을 해주세요.^^a
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입