널값인 경우와 널값이 아닌경우 나눌 경우.. 스칼라서브쿼리 0 10 6,037

by 조수열 Null 스칼라서브쿼리 NVL NVL2 [2009.01.12 17:25:14]


안녕하세요?

    Select    col1
    From      tab1
    Where   dt between ’20080101’ and ’20081231’

이라는 쿼리가 있고 tab1과 구조가 같은 (데이터는 다른) tab2 라는 테이블이 있습니다.

tab1의 col1의 값이 null 일경우는 tab2의 값을 조회되게 하고 싶은데요

예를들어 뭐 이런식이 되겟져...

    select nvl2((select col1 from tab2 where dt between ’20080101’ and ’20081231’),tab2.col1,tab1.col1)
    from tab1
    where dt between ’20080101’ and ’20081231’

스칼라서브쿼리나, NVL, NVL2 다 생각하고 대입해봐도

Where조건이 복수의 row를 리턴하다보니 사용할수가 없네요

 

어떻게 해야할까요.. 진정 방법은 없는것일까요.. 도움 부탁드립니다.

제 설명이 부족하다면 댓글 달아주세요

by 조수열 [2009.01.12 17:31:48]
스칼라서브쿼리로 검색하니 리턴값이 1개인 경우를 극복하는 글이 있기는한데
예제가 너무 어렵네요 @,@
누가 설명좀...ㅜㅜ

by 마농 [2009.01.12 17:36:49]
우선 두 테이블간의 관계와 조인에 대해서 검색해보심이 좋을듯 합니다.

by 김강환 [2009.01.12 17:38:03]
스칼라 서브쿼리는 반드시 one row,one column만을 리턴해야 합니다. 그런데 질문하신 분의 스칼라서브 쿼리를 보면

select col1 from tab2 where dt between '20080101' and '20081231'

로 되어있죠. 그럼 dt between '20080101' and '20081231' 에 해당하는 모든 로우가 대상이 되버려서 에러가 납니다.

스칼라 서브쿼리를 사용하려면 두개 테이블에 대한 조인조건이 있어야합니다.

select nvl2((select col1 from tab2 B where B.dt =A.dt),tab2.col1,tab1.col1)
from tab1 A
where dt between '20080101' and '20081231'

해결책을 찾을려면 일단 두개 테이블의 관계 1:1인지,1:다인지,다:다인지 그리고 두 테이블의 조인칼럼은 dt밖에 없는 건지 이런 점들이 먼저 고려되어야 할듯합니다.

(근데 꼬리말 달기가 좀 이상하넹 --)

그러나 만일 이 조건을 주었슴에도 불구하고 복수개의 로우가 리턴된다면 똑같은 문제가 발생되고 그럼 결국 스칼라서브 쿼리에서 distinct로 압축하거나 일반 조인으로 해결해야 합니다.

by 조수열 [2009.01.12 17:38:47]
음... 조언 감사합니다.
일단 먼저 제안하신 방법으로 시도하고 또 고민해보겠습니다 감사합니다.

by 김강환 [2009.01.12 17:38:47]
덧글달기가 어째...글자가 뒤죽박죽으로 나오네 ?????

by 이재현 [2009.01.12 18:00:30]
쪼렙입니다... : )

음.. 잘 모르지만..

저의 생각은 구조가 같은 테이블이면...

두 테이블을 조인을 걸어서..

DECODE로 NULL CHECK를 해주고. 참(NULL)이면.. 다른테이블꺼 가져오면

될듯합니다..굳이 스칼라서브커리로 유니크ID를 가져와서 돌릴필요는 없다구

봅니다.

음.... 제 기억(주관적)으로는 스칼라 서브커리는 일종의 펑션으로 알고있습니다.

로우 테이타 만큼 펑션을 돌린다면..

속도가 느린걸루 알고있습니다.(단 인텍스를 탄다면.. 갠찮은걸루 알고있습니다.)

음.. 제가 잘못알고 있다면 양해 바라며.... 가르쳐 주세요 ㅠ

WITH T1 AS(
SELECT '1' AS ID , 'KIM' AS NAME FROM DUAL UNION ALL
SELECT '2' AS ID , '' AS NAME FROM DUAL UNION ALL
SELECT '3' AS ID , 'LEE' AS NAME FROM DUAL UNION ALL
SELECT '4' AS ID , 'YU' AS NAME FROM DUAL UNION ALL
SELECT '5' AS ID , '' AS NAME FROM DUAL UNION ALL
SELECT '6' AS ID , 'YU' AS NAME FROM DUAL

),
T2 AS (
SELECT '1' AS ID , 'KIM' AS NAME FROM DUAL UNION ALL
SELECT '2' AS ID , 'LEE' AS NAME FROM DUAL UNION ALL
SELECT '3' AS ID , 'LEE' AS NAME FROM DUAL UNION ALL
SELECT '4' AS ID , 'YU' AS NAME FROM DUAL UNION ALL
SELECT '5' AS ID , 'YU' AS NAME FROM DUAL UNION ALL
SELECT '6' AS ID , 'YU' AS NAME FROM DUAL
)
SELECT
A.ID
, DECODE(A.NAME,NULL,B.NAME,A.NAME) AS NAME
FROM
T1 A
, T2 B
WHERE A.ID = B.ID

by 손님2 [2009.01.12 19:33:06]
두 테이블이 어떤 관계인지 알야야 답글이 달릴 듯한데요. 예를 들어 tab1에 20080101의 값이 1개면 tab2에 20080101의 값이 1개인지.. tab1에 null값이 있으면 tab2의 어떤 값을 가져와야하는지가 기술되어있어야.. 설명이 되겠죠.
스칼라서브쿼리 안에서 해당 값만 가져오는 것은 왜 안 되는 건가요?

by 조수열 [2009.01.13 12:23:43]
많은 분들이 답 달아주셧네요
tab1이 원래 내역이고 tab2가 수정내역입니다.
tab1의 내역을 출력하되 해당일에 수정내역이 있는경우(tab2에)
수정내역을 대신 출력해야하는것이지요.

서브쿼리의 조건절이 between and 절이라서 여러 행이 리턴 되기때문에
스칼라 서브쿼리로 적용할수가 없더라구요..(제가 잘 모르는것인지.)

by 마농 [2009.01.13 13:17:58]
SELECT t1.pk, t1.dt, NVL(t2.col1,t1.col1) col1
FROM tab1 t1, tab2 t2
WHERE t1.dt BETWEEN '20080101' and '20081231'
AND t1.pk = t2.pk(+)

by 조수열 [2009.01.14 08:46:52]
마농님 감사합니다.^^
outer join 을 써서 하니까 되는군요. 항상 아우터조인보면서 저건 도대체 언제 써먹나 햇는데 쓸날이 오네요.
질문이 참 허접햇는데 잘 이해해주시고 명쾌한 답변 감사드립니다.
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입