为啥要在字段上使用 LEFT JOIN,然后在 WHERE 子句中将其过滤掉?

Posted

技术标签:

【中文标题】为啥要在字段上使用 LEFT JOIN,然后在 WHERE 子句中将其过滤掉?【英文标题】:Why would LEFT JOIN on a field to then later filter it out in WHERE clause?为什么要在字段上使用 LEFT JOIN,然后在 WHERE 子句中将其过滤掉? 【发布时间】:2019-04-21 18:04:04 【问题描述】:

查询

SELECT ID, Name, Phone 
FROM Table1 
LEFT JOIN Table2 ON Table1.ID = Table2.ID
WHERE Table2.ID IS NULL

问题

很难理解为什么有人会离开加入 ID 然后在where子句中设置为NULL? 我在这里遗漏了什么吗?这有什么意义吗? 我们可以完全省略Table2 吗?就像根本不加入一样?

任何帮助将不胜感激。

【问题讨论】:

How to select rows with no matching entry in another table?的可能重复 查找 NOT EXISTS 记录的方法不同。有时这种方式更有效。 这也是查找孤立记录的好方法(如果 FK 约束未强制执行或不存在) 常被称为左反连接 我同意你的观点 OP - 我也不明白为什么人们会这样做(以及许多其他事情)。 Zohar 很好地解释了 IMO。 【参考方案1】:

你在问题​​中的查询基本上相当于下面的查询:

SELECT ID, Name, Phone 
FROM Table1 
WHERE NOT EXISTS
(
    SELECT 1
    FROM  Table2 
    WHERE Table1.ID = Table2.ID
)

意思是选择表1中所有与表2没有关联记录的记录。

两个查询的执行计划很可能是相同的(就我个人而言,我从未见过它们产生不同执行计划的情况,但我不排除这种可能性),因此两个查询应该同样有效,由您决定是左连接还是存在语法对您来说更具可读性。

【讨论】:

【参考方案2】:

这是实现antijoin的关系型数据库操作的一种方式,在sql server的术语中叫做anti semi join。这本质上是“从一个表中获取不在另一个表中的行”。

我想不到的方法是:

select cols from t1 left join t2 on t1.key=t2.key where t2.key is null

select cols from t1 where key not in (select key from t2)

select cols from t1 where not exists (select 1 from t2 where t1.key=t2.key)

甚至

select * from t1 where key in (select key from t1 except select key from t2)

这些方法之间存在一些差异(最明显的是,在 not in 的情况下存在 null 处理的危险),但它们通常做的相同。


解决您的问题:

很难理解为什么有人会离开加入一个 ID 和 然后在where子句中设置为NULL?

如前所述,为了排除 t1 中存在于 t2 中的结果

我们可以完全省略 Table2 吗?就像根本不加入一样?

如果您不使用连接(或其任何等效替代方案),您将获得更多结果,因为 table1 中与 table2 中的任何行具有相同 id 的行也将被返回。

【讨论】:

【参考方案3】:

如果加入条件列的 ID 为空值,那么根据我的理解,这是糟糕的数据库设计。

根据您在下面的查询。以下是为什么 where 子句有意义的可能场景

    我假设您的姓名和电话号码来自 table2,然后您尝试查找 ID 为空的姓名和电话号码。

    如果姓名和电话号码来自 table1 并且 table 2 只是具有 ID 连接并且没有从 table 2 中选择任何内容,那么 where 子句完全是浪费。

    选择 ID, 姓名, 电话 从 表格1 左连接 表2 在 表 1.ID = 表 2.ID 在哪里 Table2.ID 为空

基本上在上述常见的业务场景中,当来自右侧的任何值具有非相关数据且不需要成为数据集的一部分时,开发人员将 where 子句过滤条件放在左连接中,然后将其过滤掉。

【讨论】:

【参考方案4】:

我认为你应该为你的表设置一个别名,并指定每列来自哪个表。

假设 Name 来自表一,Phone 来自表二且 ID 在两者中是通用的,那么上面提到的 Left join 可能有助于获取所有没有电话号码的用户。

表 1 身份证号 1 约翰·史密斯 2简·多伊

表 2 身份证电话 2 071 555 0863

不带 where 子句的左连接 ID 姓名 电话 1 约翰·史密斯 NULL 2 简·多伊 071 555 0863

用 where 子句左连接 ID 姓名 电话 1 约翰·史密斯 NULL

【讨论】:

以上是关于为啥要在字段上使用 LEFT JOIN,然后在 WHERE 子句中将其过滤掉?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL (# of Products in Category) COUNT() w/ LEFT JOIN & ON 2 表

MySQL 的 2 个字段上的 SQL LEFT-JOIN

MySql 之 left join 查询结果

对于大量left join 的表查询,可以在关键的 连接节点字段上创建索引。

为啥以及何时在 WHERE 子句中带有条件的 LEFT JOIN 不等于在 ON 中的相同 LEFT JOIN? [复制]

Left Outer Join 的条件谓词评估较晚,导致性能问题。甲骨文 8i