在这个候选答案中,断言在某些涉及某些
JOIN
子句的情况下LEFT JOIN
比WHERE
更好,因为它不会混淆查询规划器并且不是“毫无意义的”。断言/假设对任何人来说都应该是显而易见的。
请进一步解释或提供链接以供进一步阅读。
实际上,
WHERE
条件和 JOIN
的 [INNER] JOIN
条件在 PostgreSQL 中是 100% 等效的。 (不过,使用显式 JOIN
条件使查询更易于阅读和维护是一个很好的做法)。
对于连接右侧表上的 LEFT JOIN
与
WHERE
条件的组合,not也是如此。
LEFT JOIN
的目的是保留连接左侧的所有行,无论右侧是否匹配。如果未找到匹配项,则该行将使用右侧列的空值进行扩展。 说明书:
LEFT OUTER JOIN
首先,执行内连接。然后,对于T1中不满足与T2中任何行的连接条件的每一行,连接行 在 T2 的列中添加空值。因此,连接表 T1 中的每一行始终至少有一行。
如果您随后应用一个
WHERE
条件,该条件要求右侧表的列上除空值之外的其他内容,则您将无效该效果并强制将 LEFT [OUTER] JOIN
转换为像普通 [INNER] JOIN
一样工作,只是(可能)由于查询计划更复杂,成本更高。
在具有许多连接表的查询中,Postgres(或任何 RDBMS)很难找到最佳(甚至是好的)查询计划。理论上连接表的可能序列数量会因子增长(!)。 Postgres 使用 “通用查询优化器” 来完成任务,并且有一些设置会影响它。
如上所述,使用误导性的
LEFT JOIN
来混淆查询,会使查询规划器的工作变得更加困难,会误导人类读者,并且通常会暗示查询逻辑中的错误。
由此产生的问题的相关解答:
等等
考虑以下示例。我们有两个表,DEPARTMENTS 和 EMPLOYEES。
部分部门还没有员工。
此查询使用内部联接来查找员工 999 工作的部门(如果有),否则什么也不显示(甚至不显示员工或其姓名):
select a.department_id, a.department_desc, b.employee_id, b.employee_name
from departments a
join employees b
on a.department_id = b.department_id
where b.employee_id = '999'
下一个查询使用外连接(部门和员工之间的左连接)并查找员工 999 工作的部门。但是,如果员工不在任何部门工作,它也不会显示员工的 ID 或其姓名。这是因为 WHERE 子句中使用了外部连接表。如果没有匹配的部门,则将为空(不是 999,即使员工中存在 999)。
select a.department_id, a.department_desc, b.employee_id, b.employee_name
from departments a
left join employees b
on a.department_id = b.department_id
where b.employee_id = '999'
但是考虑这个查询:
select a.department_id, a.department_desc, b.employee_id, b.employee_name
from departments a
left join employees b
on a.department_id = b.department_id
and b.employee_id= '999'
现在标准位于 on 子句中。因此,即使该员工在任何部门工作,他仍然会被返回(他的 ID 和姓名)。部门列将为空,但我们得到结果(员工方面)。
您可能认为您永远不想在 WHERE 子句中使用外部连接表,但情况不一定如此。不过,由于上述原因,通常情况下是这样。
假设您希望所有部门都没有员工。然后您可以运行以下命令,它确实使用了外连接,并且外连接表在 where 子句中使用:
select a.department_id, a.department_desc, b.employee_id
from departments a
left join employees b
on a.department_id = b.department_id
where b.employee_id is null
^^ 显示没有员工的部门。
上述可能是您想要在 WHERE 子句而不是 ON 子句中使用外连接表的唯一合法原因(我认为这就是您的问题;内连接和外连接之间的区别是一个完全不同的主题) .
一个好的查看方法是:使用外连接来允许空值。那么为什么要使用外连接并规定字段不应为空且应等于“XYZ”?如果值必须是“XYZ”(非空),那么为什么要指示数据库允许返回空值呢?这就像说了一件事,然后又推翻它。