无法理解 MySQL 的自连接左连接查询。

huangapple go评论82阅读模式
英文:

Can't understand the mysql self left-join query

问题

以下是您要翻译的内容:

我遇到一个查询,其中包括以下内容,

  1. SELECT it1.survey_set_id, it1.type, it1.value FROM survey_condition_filter it1 LEFT JOIN survey_condition_filter it2 ON(it1.survey_set_id = it2.survey_set_id AND it2.type = 3002) WHERE it1.type IN (2000, 2001, 2002) AND it2.value IS NULL;

为什么在上面的查询中使用了自连接左连接?

  1. SELECT survey_set_id, type, value FROM survey_condition_filter WHERE type IN (2000, 2001, 2002);

上面的查询不等同于第一个使用了自连接左连接的查询吗?因为查询也只是过滤了 IN (2000, 2001, 2002) AND it2.value IS NULL。我对这里使用连接查询感到困惑,无法真正理解第一个查询的工作方式。

这是表格 survey_condition_filter

  1. +---------------+--------------+------+-----+---------+-------+
  2. | Field | Type | Null | Key | Default | Extra |
  3. +---------------+--------------+------+-----+---------+-------+
  4. | survey_id | bigint | NO | PRI | NULL | |
  5. | survey_set_id | bigint | NO | PRI | NULL | |
  6. | type | int | NO | PRI | NULL | |
  7. | condition | tinyint | NO | PRI | NULL | |
  8. | value | varchar(15) | NO | PRI | NULL | |
  9. | display_value | text | NO | | NULL | |
  10. | order | int | YES | | NULL | |
  11. | created_at | datetime | NO | | NULL | |
  12. | created_by | varchar(255) | YES | | NULL | |
  13. | updated_at | datetime | NO | | NULL | |
  14. | updated_by | varchar(255) | YES | | NULL | |
  15. | deleted_at | datetime | YES | | NULL | |
  16. | deleted_by | varchar(255) | YES | | NULL | |
  17. +---------------+--------------+------+-----+---------+-------+
英文:

I come across a query which is,

  1. SELECT it1.survey_set_id, it1.type, it1.value FROM survey_condition_filter it1 LEFT JOIN survey_condition_filter it2 ON(it1.survey_set_id = it2.survey_set_id AND it2.type = 3002) WHERE it1.type IN (2000, 2001, 2002) AND it2.value IS NULL;

Why is self left-join is used in the above query.

  1. SELECT survey_set_id, type, value FROM survey_condition_filter WHERE type IN (2000, 2001, 2002);

isn't the above query is equivalent to the first query which used self left-join. since the query is just also filtering the IN (2000, 2001, 2002) AND it2.value IS NULL. I am confused the use of join query here and can't really understand the working of the first query.

This is table survey_condition_filter

  1. +---------------+--------------+------+-----+---------+-------+
  2. | Field | Type | Null | Key | Default | Extra |
  3. +---------------+--------------+------+-----+---------+-------+
  4. | survey_id | bigint | NO | PRI | NULL | |
  5. | survey_set_id | bigint | NO | PRI | NULL | |
  6. | type | int | NO | PRI | NULL | |
  7. | condition | tinyint | NO | PRI | NULL | |
  8. | value | varchar(15) | NO | PRI | NULL | |
  9. | display_value | text | NO | | NULL | |
  10. | order | int | YES | | NULL | |
  11. | created_at | datetime | NO | | NULL | |
  12. | created_by | varchar(255) | YES | | NULL | |
  13. | updated_at | datetime | NO | | NULL | |
  14. | updated_by | varchar(255) | YES | | NULL | |
  15. | deleted_at | datetime | YES | | NULL | |
  16. | deleted_by | varchar(255) | YES | | NULL | |
  17. +---------------+--------------+------+-----+---------+-------+

答案1

得分: 0

这是一种反连接。我们外连接一张表,然后仅保留外连接的行(通过在此应用 WHERE ... it2.value IS NULL)。在我看来,使用直接的 NOT EXISTS(或在许多情况下使用 NOT IN)更为常见,也更易读。

  1. 选择 it1.survey_set_idit1.typeit1.value
  2. survey_condition_filter it1 中选择
  3. 其中 it1.type (200020012002)
  4. 并且 NOT EXISTS
  5. (
  6. 选择 null
  7. survey_condition_filter it2 中选择
  8. 其中 it2.survey_set_id = it1.survey_set_id
  9. 并且 it2.type = 3002
  10. );

此查询的作用很明显:选择所有类型为 2000/2001/2002 的行,其中同一 survey_set_id 不存在类型为 3002 的行。

如果 survey_set_id 是非空列,则可以使用 NOT IN,这样查询会变得稍微更短:

  1. 选择 it1.survey_set_idit1.typeit1.value
  2. survey_condition_filter it1 中选择
  3. 其中 it1.type (200020012002)
  4. 并且 it1.survey_set_id NOT IN
  5. (
  6. 选择 it2.survey_set_id
  7. survey_condition_filter it2 中选择
  8. 其中 it2.type = 3002
  9. );
英文:

This is an anti join. We outer join a table, but then only keep the outer joined rows (by applying WHERE ... it2.value IS NULL here). It is much more common - and much more readable in my opinion - to use a straight-forward NOT EXISTS (or NOT IN in many situations).

  1. SELECT it1.survey_set_id, it1.type, it1.value
  2. FROM survey_condition_filter it1
  3. WHERE it1.type IN (2000, 2001, 2002)
  4. AND NOT EXISTS
  5. (
  6. SELECT null
  7. FROM survey_condition_filter it2
  8. WHERE it2.survey_set_id = it1.survey_set_id
  9. AND it2.type = 3002
  10. );

What this query does is obvious: select all type 2000/2001/2002 rows where not exists a 3002 row for the same survey_set_id .

If survey_set_id is a non-nullable column, you can use NOT IN, which gets the query even a tad shorter:

  1. SELECT it1.survey_set_id, it1.type, it1.value
  2. FROM survey_condition_filter it1
  3. WHERE it1.type IN (2000, 2001, 2002)
  4. AND itl.survey_set_id NOT IN
  5. (
  6. SELECT it2.survey_set_id
  7. FROM survey_condition_filter it2
  8. WHERE it2.type = 3002
  9. );

huangapple
  • 本文由 发表于 2023年5月10日 13:23:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215140.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定