更详细地解释JOIN与LEFT JOIN和WHERE条件性能建议

时间:2014-07-21 23:44:59

标签: sql postgresql join left-join where

this candidate answer中,在某些涉及某些JOIN子句的情况下,LEFT JOIN优于WHERE,因为它不会混淆查询规划器而不是&# 34;无意义&#34 ;.断言/假设是任何人都应该明白。

请进一步解释或提供进一步阅读的链接。

2 个答案:

答案 0 :(得分:22)

考虑以下示例。我们有两个表,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所在的部门。但是,如果他们不在任何部门工作,也不会显示员工的身份证或他或她的名字。这是因为在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子句中。因此,即使该员工在任何部门工作,他仍将被退回(他的身份证和姓名)。部门列将为空,但我们得到一个结果(员工方)。

您可能认为您永远不想在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&#39 ;?如果值必须是' XYZ' (不是null),那么为什么要指示数据库允许空值返回?这就像说一件事,然后再压倒它。

答案 1 :(得分:16)

有效地,WHERE JOIN条件和[INNER] JOIN条件在PostgreSQL中是100%等效的。 (尽管如此,使用显式JOIN条件使查询更易于阅读和维护是一种很好的做法。

对于LEFT JOIN,并且在联接右侧的表上加上WHERE条件,为真。 LEFT JOIN的目的是保留连接左侧的所有行,而不管右侧是否匹配。如果未找到匹配项,则右侧的列将使用NULL值进行扩展。 The manual:

  

LEFT OUTER JOIN

     

首先,执行内连接。然后,对于T1中不满足T2中任何行的连接条件的每一行,连接一行   在T2的列中添加空值。这样,联合表   在T1中每行至少有一行。

如果您在右侧的表格列上应用WHERE条件,则会使效果无效,并强制将LEFT JOIN转换为普通JOIN的工作,只需更昂贵由于更复杂的查询计划。

在具有许多连接表的查询中,Postgres(或任何RDBMS)很难找到最佳(甚至是好的)查询计划。连接表的理论上可能的序列数增长 factorially (!)。 Postgres使用"Generic Query Optimizer"来完成任务,并且有一些设置可以影响它。

如上所述,使用误导性LEFT JOIN对查询进行模糊处理会使查询规划器的工作更加困难,对于人类读者来说会产生误导,并且通常会暗示查询逻辑中存在错误。

由此引发的问题的许多相关答案: