SQL:"NOT IN"替代选择基于*不同*行的值的行?

11 mysql performance subquery

如何创建一个返回由子查询修改的结果的SQL语句,或者一个处理您尝试返回的信息的连接或其他内容?

例如:

CREATE TABLE bowlers (
bowling_id int4 not null primary key auto_increment,
name text,
team text
);
Run Code Online (Sandbox Code Playgroud)

有人可能错误地在多个团队中:

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');
Run Code Online (Sandbox Code Playgroud)

所以homer不能决定他的球队,所以他两个都在.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');
Run Code Online (Sandbox Code Playgroud)

导致:

+-----------------------+----------------+
| 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)
Run Code Online (Sandbox Code Playgroud)

你知道,这太棒了!

性能将受到影响,因为子查询将针对查询的每个结果运行,这是从A到D的B.对于几行非常好,对于数十万行来说非常糟糕.

什么是更好的方法?我主要是认为自我加入可以做到这一点,但我无法理解如何做到这一点.

有没有其他方法可以做到这一点,不使用, NOT IN( SELECT ... )

此外,这类问题的名称是什么?

RBa*_*ung 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;
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

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
    );
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这被称为"左反半连接".