2009-08-17 4 views
11

반환하려는 정보를 처리하는 하위 쿼리 또는 조인 또는 다른 결과로 수정 된 결과를 반환하는 SQL 문을 어떻게 작성합니까? 예를 들어SQL : "다른"행의 값을 기반으로 행을 선택하는 "NOT IN"대안?

:

INSERT INTO `bowlers` (`name`, `team`) VALUES 
('homer', 'pin pals'), 
('moe', 'pin pals'), 
('carl', 'pin pals'), 
('lenny', 'pin pals'), 
('homer', 'The homer team'), 
('bart', 'The homer team'), 
('maggie', 'The homer team'), 
('lisa', 'The homer team'), 
('marge', 'The homer team'), 
('that weird french guy', 'The homer team'); 

그래서 homer 자신의 팀에 결정할 수없는, 그래서 그는 모두의 :

CREATE TABLE bowlers (
bowling_id int4 not null primary key auto_increment, 
name text, 
team text 
); 

누군가가 잘못 하나 개 이상의 팀에있을 수 있습니다. Do'h!

나는 the homer team에있는 모든 사람을 알고 싶습니다. 누구도 pin pals 팀에 속해 있지 않습니다. 내가 할 수있는 최선은 이것이다 :

SELECT a.name, a.team 
    FROM bowlers a where a.team = 'The homer team' 
    AND a.name 
    NOT IN (SELECT b.name FROM bowlers b WHERE b.team = 'pin pals'); 

이 결과 : 당신이 알고,

+-----------------------+----------------+ 
| name     | team   | 
+-----------------------+----------------+ 
| bart     | The homer team | 
| maggie    | The homer team | 
| lisa     | The homer team | 
| marge     | The homer team | 
| that weird french guy | The homer team | 
+-----------------------+----------------+ 
5 rows in set (0.00 sec) 

, 화려한!

서브 쿼리는 B가 몇 행의 D. 위대한는 A에 수천의 수백 꽤 나쁜 쿼리의 결과를 실행하는 것입니다으로 성능이 떨어질 수 행.

더 좋은 방법은 무엇입니까? 나는 대부분 자기 조인이 트릭을 할 것이라고 생각하지만, 어떻게 해야할지에 대해 머리를 감쌀 수는 없다.

사용하지 않고이 작업을 수행하는 다른 방법이 있습니까는 NOT IN(SELECT ...) 또한

, 문제의이 유형의 이름은 무엇입니까?

+1

왼쪽으로 외부로 다시 가입하는 것이 좋습니다. –

답변

15

:

SELECT a.name, a.team 
FROM bowlers a 
LEFT OUTER JOIN bowlers b ON a.name = b.name AND b.team = 'pin pals' 
WHERE a.team = 'The homer team' 
AND b.name IS NULL; 

이처럼 할 수도 있습니다 : 그런데

SELECT a.name, a.team 
FROM bowlers a 
WHERE a.team = 'The homer team' 
AND NOT EXISTS (SELECT * FROM bowlers b 
    WHERE b.team = 'pin pals' 
    AND a.name = b.name 
    ); 

, 이것은 "왼쪽 안티 - 세미하세요"라고합니다.

+0

Brilliant! 귀하의 첫 번째 예제는 확실히 내 문제에 대한 개선입니다. 조금 느린 (MySQL 버전 5.0.37) 그러나 몇 가지 ... 아직 실행 중입니다. 적어도 이제는 돌아갑니다! (Left Anti-Semi Join)에 감사드립니다. –

2

LEFT JOIN 수 있으며 조인 된 테이블에 데이터가없는 (모든 null입니다) 있는지 확인하십시오. 이처럼

SELECT a.name, a.team 
    FROM bowlers a 
    LEFT JOIN bowlers b 
     ON b.name = a.name AND b.team = 'pin pals' 
    WHERE a.team = 'The homer team' 
    AND a.name 
    -- the join has to fail for this to be null 
    AND b.bowling_id IS NULL 
+0

이것은 확실히 작동하지만, 서브 쿼리보다 다소 효율적입니까? 조인에 더 많은 오버 헤드가있는 것 같지만 잘 모르겠습니다. – chrissr

+0

테이블 구조, 사용 가능한 인덱스, 테이블의 행 수 등에 따라 많이 달라집니다. 팀 A 또는 팀 B에 몇 명입니까? –