这两个查询为啥以及如何工作
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 约束,或者它是主键的一部分),那么两个查询将给出相同的输出。
【讨论】:
以上是关于这两个查询为啥以及如何工作的主要内容,如果未能解决你的问题,请参考以下文章