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'
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'
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
2条答案
按热度按时间oipij1gg1#
实际上,
[INNER] JOIN
的WHERE
条件和JOIN
条件在PostgreSQL中是100%等效的。(不过,使用显式的JOIN
条件使查询更容易阅读和维护是一个好的做法)。对于
LEFT JOIN
与WHERE
条件组合在连接右侧的表上,情况也是如此。LEFT JOIN
的目的是保留连接左侧的所有行,而不管右侧是否匹配。如果没有找到匹配,则将右侧的列扩展为空值。手册:LEFT OUTER JOIN
个首先,执行内部联接。然后,对于T1中与T2中的任何行都不满足联接条件的每一行,在T2的列中添加一个具有空值的联接行。因此,联接表中的T1中的每一行始终至少有一行。
如果您随后应用一个
WHERE
条件,该条件要求在右侧表的列上使用除空值以外的其他值,则会使效果无效,并强制将LEFT [OUTER] JOIN
转换为普通的[INNER] JOIN
,只是(可能)由于更复杂的查询计划而更昂贵。在一个有许多连接表的查询中,Postgres(或任何RDBMS)很难找到最好的(甚至是一个好的)查询计划。理论上可能连接表的序列的数量 factorially(!)。Postgres使用“Generic Query Optimizer”来完成任务,并且有一些设置来影响它。
使用误导性的
LEFT JOIN
混淆查询,使查询规划器的工作更加困难,对人类读者来说是误导性的,通常暗示查询逻辑中的错误。由此产生的问题的相关解答:
等
0tdrvxhp2#
考虑下面的例子,我们有两个表,DEPARTMENTS和EMPLOYEES。
有些部门还没有雇员。
这个查询使用了一个内部连接,它查找员工999工作的部门(如果有的话),否则它什么都不显示(甚至不显示员工或他或她的名字):
字符串
下一个查询使用外部联接(留在部门和员工之间),查找员工999工作的部门。但是,如果员工不在任何部门工作,它也不会显示员工的ID或姓名。这是因为在WHERE子句中使用了外部联接表。如果没有匹配的部门,它将为空(不是999,即使999存在于员工中)。
型
但是考虑一下这个查询:
型
现在条件在on子句中。所以即使这个员工没有在任何部门工作,他仍然会被返回(他的ID和姓名)。部门列将为null,但我们得到一个结果(员工端)。
你可能会认为你永远不想在WHERE子句中使用外部连接表,但这并不一定,通常情况下是这样的,尽管原因如上所述。
假设你想让所有部门都没有员工,那么你可以运行下面的命令,它使用了一个外部连接,外部连接表在where子句中使用:
型
显示没有员工的部门。
以上可能是您希望在WHERE子句中使用外部连接表而不是ON子句的唯一合理原因(我认为这就是您的问题所在;内部和外部连接之间的区别是一个完全不同的主题)。
一个很好的方法是这样的:你使用外部连接来允许空值。为什么你要使用外部连接并说一个字段不应该是空值,应该等于'XYZ'?如果一个值必须是'XYZ'(不是空值),那么为什么要指示数据库允许空值返回?这就像说了一件事,然后覆盖它。