2014-11-05 5 views
0
SELECT DISTINCT a.value 
FROM a LEFT JOIN b 
    ON a.value = b.value 
     AND (b.field IS NULL OR b.field != 'my_string'); 

SELECT a.value 
FROM a 
WHERE a.value NOT IN 
    (SELECT value 
    FROM b 
    WHERE b.field = 'my_string'); 

내가 읽은 것부터 LEFT JOIN이 더 빠릅니다. 하지만 DISTINCT는 비효율적 인 쿼리를위한 코드 냄새라고 읽었습니다. 최악의 시나리오에서 어떤 쿼리가 더 잘 수행되는지 결정하는 방법은 무엇입니까?다른 테이블에없는 행을 선택하십시오.

편집 : 죄송합니다. id는 기본 키가 아니며 단지 다른 필드입니다. 나는 그것을 가치로 바꿀 것이다.

EDIT2 : 모든 사람이 내 첫 번째 쿼리에 매달린 것처럼 보입니다. 대신이 모양처럼 보일 것입니다. 논리가 동일하지 않습니까?

SELECT DISTINCT a.value 
FROM a LEFT JOIN b ON a.value = b.value 
WHERE (b.field IS NULL OR b.field != 'my_string'); 

EDIT3 : 샘플 피들. http://sqlfiddle.com/#!2/500ea/1

EDIT4 : 대답을 수락합니다. IN()SELECT 상태에서 상기 필터를 수행하기 위해 한 번 모든 행에 대해 실행되어야하기 때문에 일반적으로 http://sqlfiddle.com/#!2/500ea/8

답변

6

첫 번째 가입은 비관적입니다. 모든 a.id 값을 a에 반환합니다. left join은 첫 번째 테이블의 모든 행과 두 번째 테이블의 일치하는 행을 유지합니다. 난 당신이하려는 생각 :

SELECT a.id 
FROM a LEFT JOIN 
    b 
    ON a.id = b.id AND b.field = 'my_string' 
WHERE b.field IS NULL; 

distincta.id이 아니라, 고유 ID라고 가정하면, 불필요한해야합니다.

대안은 not exists을 사용하는 것입니다

성능
SELECT a.id 
FROM a 
WHERE NOT EXISTS (SELECT 1 FROM b WHERE a.id = b.id AND b.field = 'my_string'); 

b(id, field)에 인덱스를 만들 수 있습니다.

+0

동일한 답변을 작성하는 동안 닌자드 +1 –

+0

맞습니다. 고맙습니다. http://sqlfiddle.com/#!2/500ea/8 – Tuan

0

NOT IN (SELECT ...)LEFT JOIN inneficient 이상이다. 작은 데이터 세트의 경우에는 문제가되지 않지만 대용량 데이터 세트의 경우 꽤 큰 두통 이 매우 비 효과적 일 수 있습니다.

관련 문제