가입하지 않은 레코드를 어떻게 찾습니까?
문제
함께 결합 된 두 개의 테이블이 있습니다.
A는 많은 b를 가지고 있습니다. b
일반적으로 당신은 할 것입니다 :
select * from a,b where b.a_id = a.id
b에 레코드가있는 A로부터 모든 레코드를 얻으려면.
B에 아무것도없는 A에서 레코드 만 얻으려면 어떻게해야합니까?
해결책
select * from a where id not in (select a_id from b)
또는이 스레드의 다른 사람들처럼 다음과 같이 말합니다.
select a.* from a
left outer join b on a.id = b.a_id
where b.a_id is null
다른 팁
select * from a
left outer join b on a.id = b.a_id
where b.a_id is null
또 다른 접근법 :
select * from a where not exists (select * from b where b.a_id = a.id)
"ENSISS"접근 방식은 내부 쿼리에 첨부 해야하는 다른 "위치"조항이있는 경우 유용합니다.
SELECT id FROM a
EXCEPT
SELECT a_id FROM b;
선택 *에서 id id in이 아닌 선택 (b에서 a_id를 선택)
OUTER 조인을 사용하는 경우 ( 'Not In'을 사용하는 것보다 훨씬 더 나은 성능을 얻을 수 있습니다.
select * from a left outer join b on a.id = b.a_id where b.a_id is null;
이것은 IN 절의 널로부터 당신을 보호하여 예상치 못한 행동을 일으킬 수 있습니다.
*를 선택하여 a id가 아닌 곳에서 (B에서 [id]를 선택하십시오. ID]는 무효가 아닙니다)
한 번의 가입의 경우 매우 빠르지 만, 외국 키로 인해 약 50 마일의 마일 레코드와 4 개 이상의 결합이있는 데이터베이스에서 레코드를 제거 할 때는 몇 분이 걸립니다. 다음과 같이 상태가 아닌 경우 사용하는 것이 훨씬 빠릅니다.
select a.* from a
where a.id NOT IN(SELECT DISTINCT a_id FROM b where a_id IS NOT NULL)
//And for more joins
AND a.id NOT IN(SELECT DISTINCT a_id FROM c where a_id IS NOT NULL)
Cascade Delete가 구성되지 않은 경우 삭제하기 위해이 접근법을 추천 할 수 있습니다. 이 쿼리는 몇 초 밖에 걸리지 않습니다.
첫 번째 접근법은입니다
select a.* from a where a.id not in (select b.ida from b)
두 번째 접근법은입니다
select a.*
from a left outer join b on a.id = b.ida
where b.ida is null
첫 번째 접근법은 매우 비쌉니다. 두 번째 접근법이 더 좋습니다.
PostgreSQL 9.4를 사용하면 "쿼리 설명"기능과 첫 번째 쿼리를 비용 = 0.00..1982043603.32. 대신 비용으로 조인 쿼리 비용 = 45946.77..45946.78
예를 들어, 나는 차량이없는 것과 호환되지 않는 모든 제품을 검색합니다. 저는 100K 제품과 1m 이상의 호환성입니다.
select count(*) from product a left outer join compatible c on a.id=c.idprod where c.idprod is null
조인 쿼리는 약 5 초를 소비했지만 서브 쿼리 버전은 3 분 후에 끝나지 않았습니다.
그것을 쓰는 또 다른 방법
select a.*
from a
left outer join b
on a.id = b.id
where b.id is null
아야, Nathan에 의해 구타 :)