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子句的一部分。

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

4

5 回答 5

6

在第二个 SQL 中,条件 h.type = 'home' 是外部连接条件的一部分,而不是结果的过滤器。对于 h.type='cell' 的所有记录,条件 h.type = 'home' 为 FALSE,因此找不到“匹配”c 行 - 所以 c.number 为空,这是您唯一的过滤 (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;
于 2008-12-05T15:16:51.027 回答
2

当做左连接时,我以这种方式处理事情。在连接中,您需要指定实际将两个表链接在一起的 anny 字段以及来自连接右侧(连接中的第二个表)的任何过滤条件(有一个例外,我很快就会谈到)。连接左侧(第一个表)的过滤条件应该在 where 子句中,否则它们会错误地影响连接,如您所见(正如 Tony 很好地解释的那样)。连接右侧应该出现在 where 子句中的唯一情况是,如果您正在该表中查找空值(即,在第一个表中但不在第二个表中的记录)。

于 2008-12-05T15:30:22.403 回答
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')
于 2015-05-08T08:43:36.137 回答
0

你可以试试这个查询,我希望它对你有用。

select * from phone_numbers
where person_id not in (select person_id from phone_numbers where type='cell')
于 2015-05-11T08:27:43.900 回答
-2

我不知道这是否会解决问题,但是...

以“and”开头的语句应该是 WHERE 子句的一部分,而不是 ON 子句的一部分。ON 子句应该包含涉及哪些列用于连接表的语句。

于 2008-12-05T15:15:09.890 回答