这两个查询为啥以及如何工作

Posted

技术标签:

【中文标题】这两个查询为啥以及如何工作【英文标题】:Why and how do these two queries both work这两个查询为什么以及如何工作 【发布时间】:2021-12-28 04:26:35 【问题描述】:

我一直在尝试使用 SQLBolts 教程学习 SQL,对于这个练习,我需要编写一个查询来显示所有没有员工的建筑物的名称,只使用 LEFT JOIN。我的答案与网站不同,我想知道为什么它们都有效。我们的解决方案之间的唯一区别是我将 WHERE 建筑物设置为 NULL 与 SQL Bolts 解决方案的 WHERE 角色为空。如果建筑价值为空,那不应该返回空值吗?同样与角色相同,当没有建筑物附加到该角色时,数据库如何知道该建筑物的角色为空值?

我的查询

SELECT building_name                                     
FROM buildings                                                  
LEFT JOIN EMPLOYEES                                        
ON buildings.building_name = EMPLOYEES.building       
WHERE building IS NULL 

SQL BOLT 查询

SELECT DISTINCT building_name, role                              
FROM buildings                                                  
LEFT JOIN employees                                               
ON building_name = building                                     
WHERE Role IS NULL                                           

Buildings (table1) and Employees (table2)

Null Values from Database

【问题讨论】:

基本上,右侧表格中与ON buildings.building_name = EMPLOYEES.building 不匹配的任何内容都将返回NULL。因此,如果您从右表WHERE right_table.column_name IS NULL 中定义任何列,您将得到相同的结果。您应该了解LEFT JOIN 的工作原理,只有您自己才能理解它是如何发生的。 @FanoFN: 不是 any 列,您应该避免使用实际上可能具有空值的列 哦,是的,没错@ysth。我的错,我可能太专注于ON 条件,以至于其他列数据的可能性是NULL 让我忘记了。 【参考方案1】:

在定义完整的表结构之前,两个查询都是不正确的。当查询数据源包含多个表副本时,每个列名必须与其表别名部分一起指定。排除 - USING 子句中使用的列名或使用 NATURAL JOIN 时的公共列,这些列可以在没有表别名的情况下使用。向后排除 - 查询在复合语句中使用,并且存在局部变量,在这种情况下必须无条件使用别名。

如果表结构声称查询文本是正确的(所有没有表别名的列都是唯一的),那么您的查询更正确,因为它在测试 NULL 时使用了 JOIN 条件中使用的列。如果Role 列可以为空并且该列中某些行包含 NULL,则“SQL BOLT 查询”可能会给出错误的结果。

如果Role 被定义为 NOT NULL(直接或间接 - 例如,根据 CHECK 约束,或者它是主键的一部分),那么两个查询将给出相同的输出。

【讨论】:

以上是关于这两个查询为啥以及如何工作的主要内容,如果未能解决你的问题,请参考以下文章

有人可以解释这两个 http 调用之间的区别以及为啥一个失败而另一个没有?

这两个 LINQ 查询有啥区别以及如何正确优化它们?

为啥 Spark 以不同的方式解释这两个查询?

为啥这两个查询之间的性能增益存在差异?

为啥这两个 NHibernate 查询会产生不同的结果?

尽管代码相同,为啥这两个 html/css 文件的工作方式不同? [关闭]