2012-05-21 4 views
0

다음 쿼리를 작성한 동료가 있습니다. 첫 번째 작품과 두 번째 않습니다. 또한 하위 쿼리에서 집계 함수를 제거하면 작동합니다. 오라클 옵티마이 저는 이상한 일을하고 있습니다. 이견있는 사람? 11.1.0.6.0 64 비트에 대해 SQL Developer 3.1에서 실행 중입니다.Oracle Optimizer 예기치 않은 결과

이 작동 :

SELECT 
    a.fd_customer_key 
, b.fd_customer_key 
, b.counter 
FROM FETCH_CUSTOMER a 
, (select fd_customer_key, count(*) as counter from fetch_customer_order group by fd_customer_key) b 
where a.fd_customer_key = b.fd_customer_key (+) 
and b.counter is null 

이되지 않습니다

SELECT 
a.fd_customer_key 
, b.fd_customer_key 
, b.counter 
FROM FETCH_CUSTOMER a 
, (select fd_customer_key, count(*) as counter from fetch_customer_order group by fd_customer_key) b 
where a.fd_customer_key = b.fd_customer_key (+) 
and b.fd_customer_key is null 
+0

우리가 작동하지 않는다고 말할 때, 어떤 행도 반환하지 않는다는 뜻입니다. – jcourtjr

+0

이 또한 , B (fd_customer_key 의해 fetch_customer_order 군으로부터 1 fd_customer_key 선택) FETCH_CUSTOMER FROM b.fd_customer_key, a.fd_customer_key 을 선택'여기서 작동 a.fd_customer_key b.fd_customer_key = (+) 및 b.fd_customer_key 널이다 ' – jcourtjr

+0

이것은 FETCH_CUSTOMER FROM b.fd_customer_key'일 a.fd_customer_key 를 선택하지 않는다 (fd_customer_key 선택 합 (1)에 의해 fd_customer_key fetch_customer_order 그룹) 여기서 B = a.fd_customer_key b.fd_customer_key (+) 이고 b.fd_customer_key가 null 인 경우 ' – jcourtjr

답변

0

보인다 FETCH_CUSTOMER_ORDER).

오라클로 당신은 당신이 NOT IN 또는 NOT EXISTS 연산자를 사용하여 최적화 프로그램이 최적의 계획을 찾을 수 있었다 안티 조인 작성이 영리 OUTER JOIN 트릭을 사용할 필요가 없습니다. 이것은 읽기 쉽고 효율적입니다.

CREATE TABLE a (ID NUMBER PRIMARY KEY); 
CREATE TABLE b (a_id NUMBER NOT NULL, DATA VARCHAR2(30)); 
INSERT INTO a (SELECT object_id FROM all_objects); 
INSERT INTO b (SELECT object_id, object_name 
       FROM all_objects WHERE object_type = 'VIEW'); 

SELECT a.id, b.a_id, b.cnt 
    FROM a, (SELECT a_id, COUNT(*) cnt FROM b GROUP BY a_id) b 
WHERE a.id = b.a_id (+) 
    AND b.cnt IS NULL; 

SELECT a.id, b.a_id, b.cnt 
    FROM a, (SELECT a_id, COUNT(*) cnt FROM b GROUP BY a_id) b 
WHERE a.id = b.a_id (+) 
    AND b.a_id IS NULL; 

당신은 두 쿼리가 행을 반환 것을 발견 할 것이다 :

어쨌든, 당신의 결과를 재현 할 수없는, 여기 내 설정이다. DB 버전은 무엇입니까?

+0

위의 예제를 시도했지만 두 경우 모두 실제로 행을 반환하지 않습니다. 버전은 11g입니다. 집계가 문제의 원인이되는 위의 또 다른 예를 추가했습니다. – jcourtjr

+0

b.a_id 필드에 고유하지 않은 색인을 추가하십시오. 두 번째 쿼리에서 '똥개'결과가 사라집니다. – jcourtjr

+0

이것은 사용중인 버전의 버그 여야합니다 : 9.2.0.5와 11.2.0.3.0에서이를 테스트했으며 두 쿼리가 동일한 결과를 반환합니다. –

2
사실

그래, 당신은 같은 방법으로 wrok 해야하는 제공되는 쿼리의 양,하지만 난 당신의 필요를 이해하는 경우도 , 주문이없는 fd_customer_key를 선택하려고하십니까?

내가 당신의 필요에 대해 다음 쿼리를 제안, 그것의 더 단순하고 덜 소모 : 당신은이 (안티 조인 해당하는 행이없는 그 FETCH_CUSTOMER에서 행을 찾을 수 있도록 노력하고있다처럼

SELECT a.fd_customer_key 
    FROM FETCH_CUSTOMER a 
WHERE NOT EXISTS (SELECT 1 
      FROM fetch_customer_order b 
     WHERE a.fd_customer_key = b.fd_customer_key) 
+0

+1, 이상하고 오류가 발생하기 쉬운 (+) 구문을 사용하지 않기 때문에 +1. 왜냐하면 그것은 성능면에서 아마도 더 좋을 것이므로'COUNT (*) '대신에'EXISTS'를 사용하기 때문입니다. OP는 관련 행이 있는지 여부를 찾아야합니다. 1,2,3,65042 관련 행이 있는지 계산할 필요가 없습니다. –

+0

이것은 더 좋은 방법이지만 Oracles 쿼리 최적화로 예상치 못한 문제를 설명하려고합니다. – jcourtjr

+0

@john : * "예기치 않은 문제"*는 "기발하고 오래되고 오류가 발생하기 쉬운 (syntax)"과 높은 상관 관계가 있습니다. * –