2008-12-05 80 views
4

考虑下表:自联接查询

mysql> select * from phone_numbers; 
+-------------+------+-----------+ 
| number  | type | person_id | 
+-------------+------+-----------+ 
| 17182225465 | home |   1 | 
| 19172225465 | cell |   1 | 
| 12129876543 | home |   2 | 
| 13049876543 | cell |   2 | 
| 15064223454 | home |   3 | 
| 15064223454 | cell |   3 | 
| 18724356798 | home |   4 | 
| 19174335465 | cell |   5 | 
+-------------+------+-----------+ 

我试图找到那些谁拥有家庭电话,但没有人的细胞。

此查询的工作:

mysql> select h.* 
    -> from phone_numbers h 
    -> left join phone_numbers c 
    -> on h.person_id = c.person_id 
    -> and c.type = 'cell' 
    -> where h.type = 'home' 
    -> and c.number is null; 
+-------------+------+-----------+ 
| number  | type | person_id | 
+-------------+------+-----------+ 
| 18724356798 | home |   4 | 
+-------------+------+-----------+ 

但是这一次没有:

mysql> select h.* 
    -> from phone_numbers h 
    -> left join phone_numbers c 
    -> on h.person_id = c.person_id 
    -> and h.type = 'home' 
    -> and c.type = 'cell' 
    -> where c.number is null; 
+-------------+------+-----------+ 
| number  | type | person_id | 
+-------------+------+-----------+ 
| 19172225465 | cell |   1 | 
| 13049876543 | cell |   2 | 
| 15064223454 | cell |   3 | 
| 18724356798 | home |   4 | 
| 19174335465 | cell |   5 | 
+-------------+------+-----------+ 

两者之间唯一的区别是的h.type = 'home'条件的位置 - 在第一个它在where子句,第二个是on子句的一部分。

为什么第二个查询不会返回与第一个查询相同的结果?

+0

在第二种情况下,你是否真的做了左连接? – 2008-12-05 15:13:11

+0

几乎想要这个只是为了艺术品而竭尽全力解释情况。 – 2008-12-05 15:35:25

回答

7

在第二个SQL中,条件h.type ='home'是外部连接条件的一部分,并且不是结果上的筛选器。对于h.type ='cell'的所有记录,条件h.type ='home'为FALSE,因此没有找到“匹配”c行 - 因此c.number为null,这是您唯一的过滤条件(WHERE) 。

在伪代码的第二次SQL是这样的:

for each row in phone_numbers h /* Note this is ALL home AND cell phones */ 
    select c.number from phone_numbers c 
    where h.person_id = c.person_id 
    and h.type = 'home' 
    and c.type = 'cell'; 
    if c.number is null (i.e. no row found) 
    display h.* 
    end if 
end loop; 
-2

我不知道这是否会解决的事情或没有,但...

开始“和”的表述应该是在WHERE子句的一部分,而不是ON子句的一部分。 ON子句应该只有有涉及哪些列用于连接表的语句。

+0

你可以在连接上添加adicional条件。这将作为在加入前发生的地方 – Sergio 2008-12-05 15:17:56

2

做当左加入我做事这种方式。在连接中,您需要指定将这两个表实际链接在一起的anny字段,以及连接的右侧(连接的第二个表)中的任何过滤条件(有一个例外,我马上就会知道)。从连接的左侧(第1个表格)过滤条件应该在where子句中,否则它们会错误地影响连接(正如Tony所说的那样)。唯一一次连接的右侧应该位于where子句中的情况是,如果您在该表中查找空值(即,第一个表中但不是第二个中的记录)。

0
SEL * 
FROM phone_numbers T1 
WHERE typeS='home' AND person_id NOT IN 
(SELECT person_id FROM phone_numbers T2 WHERE T1.person_id=T2.person_id AND typeS='cell') 
0

你可以试试这个查询,我希望它能为你工作。

select * from phone_numbers 
where person_id not in (select person_id from phone_numbers where type='cell')