自连接查询

发布于 2024-07-09 13:03:17 字数 1709 浏览 12 评论 0原文

考虑下表:

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 中code> 子句,在第二个子句中它是 on 子句的一部分。

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

Consider the following table:

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 |
+-------------+------+-----------+

I'm trying to find those people who have home phones but not cells.

This query works:

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 |
+-------------+------+-----------+

but this one doesn't:

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 |
+-------------+------+-----------+

The only difference between the two is the location of the h.type = 'home' condition - in the first it's in the where clause and in the second it's part of the on clause.

Why doesn't the second query return the same result as the first?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

深者入戏 2024-07-16 13:03:17

当进行左连接时,我以这种方式处理事情。 在联接中,您需要指定实际将两个表链接在一起的任何字段以及联接右侧(联接中的第二个表)的任何过滤条件(有一个例外,我将很快介绍)。 连接左侧的过滤条件(第一个表)应该位于 where 子句中,否则它们会错误地影响连接,正如您所看到的(正如托尼很好地解释的那样)。 只有当您在该表中查找空值(即第一个表中的记录而不是第二个表中的记录)时,联接的右侧才应位于 where 子句中。

When doing left joins I approach things this way. In the join you need to specify anny fields that actually link the two tables together and any filtering condition from the right side (2nd table in the join) of the join (with one exception, I'll get to shortly). Filtering conditions from the left side of the join(1st table) should be in the where clause or they will wrongly affect the join as you saw (and as Tony so nicely explained). The only time the right side of the join should be in the where clause is if you are looking for null values in that table (i.e., the records which are in the first table but not the second).

情深缘浅 2024-07-16 13:03:17

在第二个 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;

In the second SQL, the condition h.type = 'home' is part of the outer join conditions, and is not a filter on the results. For all records where h.type='cell', the condition h.type = 'home' is FALSE and so no "matching" c row is found - so c.number is null, which is your only filtering (WHERE) condition.

In pseudo-code your 2nd SQL works like this:

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;
眉目亦如画i 2024-07-16 13:03:17
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')
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')
影子是时光的心 2024-07-16 13:03:17

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

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

You can try this query, I hope it'll work for you.

select * from phone_numbers
where person_id not in (select person_id from phone_numbers where type='cell')
赤濁 2024-07-16 13:03:17

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

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

I don't know if this will fix things or not, but...

The statements starting with "and" should be part of the WHERE clause, not part of the ON clause. The ON clause should only have statements involving which columns are used to join the tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文