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 24117 게시물 읽기
No. 24117
아우터조인 관련, 오류좀 찾아주세요
작성자
이혁(이대리)
작성일
2005-09-16 19:49ⓒ
2005-09-16 19:53ⓜ
조회수
8,456

쿼리가 넘 길어서 폰트를 줄였습니다. ㅠㅠ;;;

제가 지금 프로젝트하는곳에서 작성한 쿼리인데

with
  param as (
    select
      SEARCH_TYPE,
      decode(REG_DT, null,'19900101',REG_DT ) as REG_DT,
      decode(REG_DT2,null,'29991231',REG_DT2) as REG_DT2,
      SEARCH_YYYYMM,
      SORT_TYPE
    from  
      (
        select
          ?     as SEARCH_TYPE,
          ?     as REG_DT,
          ?     as REG_DT2,
          ?     as SEARCH_YYYYMM,
          ?     as SORT_TYPE
        from
          dual
      )
  ),
  param_gen as (
    select
      decode(SEARCH_TYPE, 'term' , case when REG_DT > REG_DT2 then REG_DT2 else REG_DT END,
                'month', search_yyyymm||'01',
                     to_char(sysdate,'YYYYMM')||'01'
           ) as START_DATE,
      decode(SEARCH_TYPE, 'term' , case when REG_DT2 < REG_DT then REG_DT else REG_DT2 END,
                'month', SEARCH_YYYYMM||to_char(last_day(to_date(SEARCH_YYYYMM,'YYYYMM')),'DD'),
                     to_char(sysdate,'YYYYMM')||to_char(last_day(sysdate),'DD')
           ) as END_DATE
    from
      param a
  ),
  subject_master as (
    select
      b.GUBUN,
      b.MS_TYPE_SEQ,
      b.MS_TYPE_NAME,
      a.MS_CD_SEQ,
      a.MS_CD_NAME
    from
      (
        select
          case when MS_TYPE_SEQ < 200 then 'TEAM' else 'PERSON' end as GUBUN,
          MS_TYPE_SEQ,
          MS_TYPE_NAME
        from
          IMS_MS_TYPE
        where
          ISVALID='Y'
      ) b,
      (
        select
          MS_CD_SEQ,
          MS_TYPE_SEQ,
          MS_CD_NAME
        from
          IMS_MS_CD
        where
          ISVALID='Y'
      ) a
    where
      a.MS_TYPE_SEQ = b.MS_TYPE_SEQ
  ),
  html_span1 as (
    select
      a.gubun,
      min(ms_cd_seq) as MS_CD_SEQ,
      count(a.gubun) as ROW_SPAN1
    from
      subject_master a
    group
      by gubun
  ),
  html_span2 as (
    select
      a.MS_TYPE_SEQ, min(ms_cd_seq)  as MS_CD_SEQ,
      count(MS_TYPE_SEQ)       as ROW_SPAN2
    from
      subject_master a
    group by
      MS_TYPE_SEQ
  ),
  score_master as (
    select
      b.MS_TYPE_SEQ,
      b.MS_CD_SEQ,
      count(decode(b.IN_ACT_VALID, 'Y', 1, null))      as CNT_VALID_OKAY,
      count(decode(b.IN_ACT_VALID, 'N', 1, null))      as CNT_VALID_DENY,
      count(decode(b.IN_ACT_VALID, 'F', 1, null))      as CNT_VALID_WAIT,
      SUM(decode(b.IN_ACT_VALID, 'Y', a.MG_CUM_SCORE, 0))  as SUM_TOTAL
    from
      IMS_MG_SCORE a,
      IMS_MG_ACT b
    where
      a.MG_ACT_SEQ(+) = b.MG_ACT_SEQ
    and
      a.reg_dt between  to_date((select START_DATE from param_gen),'YYYYMMDD')
           and    to_date((select END_DATE  from param_gen),'YYYYMMDD')+1
    group by
      b.MS_TYPE_SEQ,
      b.MS_CD_SEQ
  )
  select
    row_number() over (order by substr(to_char(a.MS_CD_SEQ),1,1) desc, a.MS_CD_SEQ)
                                    as RNUM,
    case when a.GUBUN = 'TEAM' and c.ROW_SPAN1 is not null then '팀'
       when a.GUBUN = 'PERSON' and c.ROW_SPAN1 is not null then '개인'
       else '' end                        as GUBUN,
    decode(b.ROW_SPAN2, null, '', a.MS_TYPE_NAME)          as MS_TYPE_NAME,
    c.row_span1,
    b.ROW_SPAN2,
    a.MS_TYPE_SEQ,
    a.MS_CD_SEQ,
    a.MS_CD_NAME,
    d.CNT_VALID_OKAY,
    d.CNT_VALID_DENY,
    d.CNT_VALID_WAIT,
    d.SUM_TOTAL
  from
    subject_master a,
    html_span2 b,
    html_span1 c,
    score_master d
  where
    a.MS_CD_SEQ = b.MS_CD_SEQ(+)
  and
    a.MS_CD_SEQ = c.MS_CD_SEQ(+)
  and
    a.MS_CD_SEQ = d.MS_CD_SEQ(+)

 

노랭이로 표시해놓은 저 값이 문젠데,,,,,

분명히 score_master 안에서는 값이 존재하는데,,,,

전체 쿼리를 수행하믄 ㅡㅡ;;;;; 0 이됩니다.

다른 값들은 모두 정상인데요..저것만 저렇네요 ㅠㅠ

혹시 쿼리상에 논리적인 오류나, 기타오류같은거 발견해주실분..

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

아우터 효과가 없어질텐데요...

a.MG_ACT_SEQ(+) = b.MG_ACT_SEQ

 

이렇게 하시고

 

왜 그 밑에서는 아우터를 무효화 하셨는지...

김흥수(protokhs)님이 2005-09-18 00:37에 작성한 댓글입니다.

흥수님 ... 참 신기한 일이 생겼어요...ㅠㅠ

저 쿼리를 포기하고,,,,

저거랑 똑같은 로직으로 따로 쿼리를 작성했는데,

 

거기선 먹히네요.....ㅡㅡ 거의 똑같은데, 희안하네요.

 

어딘가에 틀린부분이 있을건데,,, 에휴

 

아..그리고, 저기서 아우터를 무효화 한 부분이 어딘지

감지를 못하겠네요...ㅡㅡ;;;;;;;

 

상세히좀 지적해주시길 ㅠㅠ....

 

관심 가져주셔서 감사합니다...

 

추석...가내 두루두루 평안하시길...

이혁(이대리)님이 2005-09-18 06:39에 작성한 댓글입니다.

 

and
      a.reg_dt between  to_date((select START_DATE from param_gen),'YYYYMMDD')
           and    to_date((select END_DATE  from param_gen),'YYYYMMDD')+1

이부분입니다...

김흥수(protokhs)님이 2005-09-19 14:59에 작성한 댓글입니다.

아 !

한가지 추가로 말씀 드릴 것이 있는데요....

 

원래 오라클에서는 아우터조인 되는 경우에 상대 표현식이 서브 쿼리여서는 안됩니다.

 

예를 들어

 

select

*

from a,b

where a.c = b.c(+)

and b.d (+) = (select d from x )

 

이런 형태는 에러입니다.

 

물론

select

*

from a,b

where a.c = b.c(+)

and b.d  = (select d from x )

이런 식으로 하면 아우터 걸린 효과가 상실됩니다.(이경우 에러는 아닙니다.)

 

그러나 웃기게도... 스칼라서브쿼리가 생긴 다음 부터는 함수로 감싸거나 식으로 사용하면 에러가 안납니다.

select

*

from a,b

where a.c = b.c(+)

and b.d (+) = to_char((select d from x) )

 

이런 식이면 에러가 안납니다..

 

뭐 여기까지는 그렇다 치더라도...

 

아주 미묘한 문제가 있습니다.

어찌보면 이건 에러라고 해야 할지도 모르는 것인데요..

 

예를 들어 보여드리면.

 

 

SQL> select * from dual a,dual b
  2  where a.dummy = b.dummy(+)
  3  and b.dummy(+) = null
  4  /

D D
- -
X

먼저 이 결과를 주의 깊게 보시고요..

 

그 다음

 

SQL> select null from dual
  2  /

N
-

                                   ==> 사실은 null이 select 되었습니다.

이 결과를 보시고요

 

그 다음 위의

두 SQL을 섞어보면 좀 이상한 결과가 옵니다.

 

SQL> select * from dual a,dual b
  2  where a.dummy = b.dummy(+)
  3  and b.dummy(+) = (select null from dual)||null
  4  /

선택된 레코드가 없습니다.

SQL> select * from dual a,dual b
  2  where a.dummy = b.dummy(+)
  3  and b.dummy(+) = (select null from dual)
  4  /
and b.dummy(+) = (select null from dual)
                                       *
3행에 오류:
ORA-01799: 열은 부속 질의에 외부결합될 수 없습니다


SQL> select * from dual a,dual b
  2  where a.dummy = b.dummy(+)
  3  and b.dummy(+) = (select null from dual)||null
  4  /

선택된 레코드가 없습니다.

좀 이상하죠?

 

제 생각에는 이거가 일종의 논리적 에러라고 생각합니다.

1. 일단 and b.dummy(+) = (select null from dual) 이거는 에러이고

    and b.dummy(+) = (select null from dual)||null 이거는 에러가 아닌점이 납득이 안가고요

2. 수학에서 동일한 값을 대입하면 동일한 결과가 와야 한데....

    and b.dummy(+) = null 이렇게 하면 결과가 나오지만...

    and b.dummy(+) = (select null from dual)||null
     이렇게 하면 안나옵니다.... 웃기죠? (select null from dual)||null

      이것도 명백히 null인데.....

 

결론적으로 제 생각에는

스칼라 서브쿼리가 생기면서..

오라클에서 자신들도 생각하지 못한 방식의 SQL들이 나오게 되고...

그에 따라 특히 null과 아우터 관련 규칙에 모순이 생긴 것이 아닌가 생각됩니다.

 

제가 정확히 기억나지 않지만...

아우터와 nvl 함수를 함께 사용할 경우도 이와 유사한 논리적 불일치성이 발견된 적이 있었습니다...

그러니 주의해서 쓰셔야합니다...

 

김흥수(protokhs)님이 2005-09-19 15:34에 작성한 댓글입니다.

에구, 갈수록 힘들어지네요,,,

일단, 원하는 결과가 나와서, 이는 그냥 종결처리했는데,

쿼리작성할때 보다 원칙적으로 접근해야겠네요...

아~~ 괴로워라 ^^ 

이혁(이대리)님이 2005-09-20 10:59에 작성한 댓글입니다.

그리고 날짜 범위는 파라미터 에선,

걍...값만 취하면 되는거라 별다른 조인문 없이

SELECT 해서 가져와서, 비교목적으로 썼는데,

그게 조인에 영향을 준다하면, 심각하게 고려해봐야겠군요...

어쨌든, 제가 쿼리 만들고도 긴가민가하는 상황이

김흥수님 말씀처럼 자주생기는거보니

오라클 쿼리가 난해해 지고 있는 느낌을 요새 많이 받네요..

ㅇ ㅏ ㄱ ㅓ 하던대로 해야지 원 ^^;;;

이혁(이대리)님이 2005-09-20 11:26에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
24120이런게 가능할까요
이문수
2005-09-20
1290
24119오라클 + PHP + APACHE에서 아파치의 환경설정
초보자
2005-09-17
1496
24118[알바급구]게시판 코딩해줄 개발자 아르바이트를 구합니다.(ASP,ORACLE)
최규운
2005-09-17
1602
24117아우터조인 관련, 오류좀 찾아주세요 [6]
이혁
2005-09-16
8456
24116connect by 사이클 검증 SQL을 검증해주시길... [3]
김흥수
2005-09-16
3683
24115이런 방식의 설계에서 키 중복을 막을 수 있는 방법이 있는지요? [2]
이승배
2005-09-16
2153
24114OCI has fetched truncated data 워닝에러 .. [1]
초보돌진
2005-09-16
4443
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.017초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다