2013-06-25 5 views
1

필터가있는 Oracle ANSI 완전 외부 조인에서 결과를 반환하지 않는 문제가 발생했습니다. 나는 모든 머펫 모든 유효한 전화 번호를 선택하려면이 테이블에서필터 (ANSI)가 예상대로 작동하지 않는 Oracle 전체 외부 조인

Table 1 - MUPPET 

ID NAME  
1 Kermit the Frog  
2 Fozzie Bear  
3 Mrs. Piggy  
4 Beaker  
5 Animal  
6 Swedish Chef 

Table 2 - PHONE 

ID MUPPET_ID  PHONE VALID 
1 1  1111111111  Y 
2 1  2222222222  N 
3 2  3333333333  Y 
4 4  4444444444  Y 
5 5  5555555555  Y 
6 6  6666666666  Y 
7 6  7777777777  N 
8 8  8888888888  Y 

... 내가 일을하고보고하고 무엇을 설명하기 위해 간단한 예를 만들었습니다. 나는 모든 muppets에게 전화 번호가 있는지 여부를 알려주고 그들이 muppet과 관련이 있는지 여부와 관계없이 모든 유효한 전화 번호를 선택하려고합니다. 이것은 내가 일을 기대 쿼리 ...

SELECT m.id muppet_id, 
     m.name, 
     p.id phone_id, 
     p.phone, 
     p.valid 
    FROM  muppet m 
     FULL OUTER JOIN 
      phone p 
     ON (M.ID = P.MUPPET_ID AND P.VALID = 'Y') 

그러나 여기에 내가 바깥에는 비 유효한 전화를 지정하지 않은 경우에도 비 유효 폰을 포함하는 결과이다 필터를

MUPPET_ID NAME PHONE_ID PHONE VALID 

1 Kermit the Frog 1 1111111111 Y 
         2 2222222222 N 
2 Fozzie Bear  3 3333333333 Y 
4 Beaker    4 4444444444 Y 
5 Animal    5 5555555555 Y 
6 Swedish Chef  6 6666666666 Y 
         7 7777777777 N 
         8 8888888888 Y 
3 Mrs. Piggy   

을 조인 나는 ...

0,123,516 마침내 나는 완전 외부의 왼쪽 부분에 하위 선택을 사용하여 찾고 있던 결과

SELECT m.id muppet_id, 
     m.name, 
     p.id phone_id, 
     p.phone, 
     p.valid 
    FROM  muppet m 
     FULL OUTER JOIN 
      (SELECT id, 
         phone, 
         valid, 
         muppet_id 
       FROM phone 
       WHERE valid = 'Y') p 
     ON (M.ID = P.MUPPET_ID) 

... 그 결과에 가입 얻을 수 있었다

MUPPET_ID NAME  PHONE_ID PHONE VALID 

1 Kermit the Frog   1 1111111111 Y 
2 Fozzie Bear    3 3333333333 Y 
4 Beaker     4 4444444444 Y 
5 Animal     5 5555555555 Y 
6 Swedish Chef    6 6666666666 Y 
           8 8888888888 Y 
3 Mrs. Piggy 

하지만 왜 이런 식으로 쿼리해야하는지 이해할 수 없습니다. 누군가 내 초기 외부 조인 필터가 예상대로 작동하지 않는 이유에 대해 설명해주십시오.

편집 :

가 더욱 흥미 롭군요. 나는이 쿼리를 실행하면

select valid from (
SELECT m.id muppet_id, 
     m.name, 
     p.id phone_id, 
     p.phone, 
     p.valid 
    FROM  muppet m 
     FULL OUTER JOIN 
      phone p 
     ON (M.ID = P.MUPPET_ID AND P.VALID = 'Y') 
) where valid = 'Y' 

을 예상대로 나는 6 개 기록을 얻을하지만이 프로그램을 실행할 때 나는 레코드가

select valid from (
SELECT m.id muppet_id, 
     m.name, 
     p.id phone_id, 
     p.phone, 
     p.valid 
    FROM  muppet m 
     FULL OUTER JOIN 
      phone p 
     ON (M.ID = P.MUPPET_ID AND P.VALID = 'Y') 
) where valid <> 'Y' 

어쩌면이 오라클의 최적화 나 드라이버의 문제입니다 반환받을 ??

+0

전체 외부 조인을 사용하면 db에 모든 레코드를 조인하고 조인 조건을 충족시키지 않는 모든 레코드를 유지할 것을 요청합니다. 당신의 예제에서'valid = 'Y'는 다른 두 레코드가 연결되지 않도록 조건의 일부입니다. 이것이 예상 된 결과입니다. – haki

+0

맞습니다.'valid = 'Y '' 조건은'on' 절 대신'where' 절에 지정해야합니다. – GriffeyDog

+0

GriffeyDog -'valid = 'Y ''의 where 절은 Piggy 여사의 마지막 기록을 반환하지 않으므로 어느 쪽도 작동하지 않습니다 – Cymon

답변

2

다른 사람들이 설명에서 설명했듯이, 이것은 필터 로직을 넣는 위치 때문입니다. 따라서 원래의 쿼리는 모든 muppets과 모든 전화 번호를 반환하고 ID가 유효 = 'Y'와 일치하면 결합 된 것으로 표시합니다. 그래서 모든 전화 번호를보고 있지만 유효한 전화 번호 만 찾습니다.

당신은 이미 알아 냈 접근 방식을, 또는 WHERE 절에 "유효"논리를 이동할 수 있습니다 : where 절 어디 유효 <> 'Y'또는 어디에 행을 폐기되어 이제

SELECT m.id muppet_id, 
     m.name, 
     p.id phone_id, 
     p.phone, 
     p.valid 
FROM  muppet m 
     FULL OUTER JOIN 
      phone p 
     ON (M.ID = P.MUPPET_ID) 
WHERE 
     P.VALID = 'Y' or P.MUPPET_ID is null; 

전화 테이블과 일치하는 것이 없습니다. "P.VALID = 'Y'"만 where 절을 작성한 경우이를 효과적으로 외부 결합으로 변환 할 수 있습니다.

즉, 내가 실제로 두 번째 버전을 선택하면 VALID = 'Y'에 색인을 사용할 수 있으므로이 색인이 존재하는 경우 위의 버전이 색인을 사용하지 않을 가능성이 높습니다. 또는 where 절에서.

+0

아! 나는 그것이 모두 지금 이해된다고 생각한다. 고맙습니다 – Cymon

0

아마도 완전 외부 조인 대신 왼쪽 외부 조인을 사용해야합니다.

완전 외부 조인에서는 m.id 및 p.valid를 기반으로 왼쪽에서 오른쪽으로 조인되지만 오른쪽에서 조인하지 않은 모든 행과 왼쪽에있는 모든 행을 반환합니다. 아무것도 가입하지 마세요.

+0

글쎄, 나는 왼쪽과 오른쪽 모두를 원합니다. 왼쪽 조인 쿼리와 오른쪽 조인 쿼리를 결합 할 수 있지만 필터링을 처리 할 수 ​​있도록 전체 외부 조인을 기대했습니다. – Cymon

+0

약간의 질문을 잘못 읽었지만 ON 절은 필터가 아닙니다. 왼쪽 테이블과 오른쪽 테이블을 함께 묶는 방법입니다 . 선택한 조인 유형 (왼쪽/오른쪽/전체)은 필터의 (정렬)입니다. – vogomatix

+0

ON 절은 필터를 함께 결합하는 방법이지만 ON 절에 필터링 값을 추가하여 내부/왼쪽/오른쪽 조인. 난 그냥 외부 조인에서 작동이 보이지 않아요 – Cymon