2014-07-21 172 views
9

this candidate answer有人断言,JOIN优于LEFT JOIN下涉及的一些WHERE条款,因为它不会混淆查询规划,而不是“毫无意义”的一些情况。断言/假设是它应该对任何人都显而易见。解释JOIN与LEFT JOIN和WHERE详细条件优化建议

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

+0

更好?他们服务于不同的目的。 JOIN是一个内部连接,LEFT JOIN是一个外部连接(与LEFT OUTER JOIN相同)。根据您的意图,您将使用外连接或内连接。 WHERE子句不应该用于连接条件。它应该用于其他标准;即。过滤。 –

+0

我在那里读到的答案是“由于LEFT JOIN(与WHERE)*有效* INNER JOIN,只需使用INNER JOIN。”我不确定它是如何“混淆”到[特定的]查询计划者,但对人类[读:我的]消费而言,IMOHO并不理想。 (同样的,可以说用于使用交叉连接时一个INNER就足够了,例如,。) – user2864740

+0

甲留下where子句使用外连接表是有效的内加入加入。但是,如果where子句不使用外连接表,否则不是这种情况。 –

回答

17

考虑下面的例子。我们有两个表格,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' 

现在的标准是在对条款。所以即使这位员工在没有任何部门工作,他仍然会被退回(他的身份证和姓名)。部门的列将为空,但我们会得到一个结果(员工方)。

你可能会认为你绝不会希望使用外部连接表的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子句的唯一合法原因(我认为这是你的问题;内连接和外连接之间的区别是完全的不同的话题)。

一个很好的方式来看待是这样的:您使用外部联接为允许空值。为什么你会使用一个外连接,并说一个字段不应该为null,并且应该等于'XYZ'?如果一个值必须是'XYZ'(非空),那么为什么要指示数据库允许空值返回?这就像说一件事,然后再压倒一件事。

11

实际上,WHERE条件和JOIN[INNER] JOIN的条件在PostgreSQL中是100%等价的。 (尽管使用明确的JOIN条件来使查询更易于阅读和维护,但这是个好习惯)。

同样是真正的LEFT JOINWHERE条件对一个表的参加权相结合。 LEFT JOIN的目的是保留连接左侧的所有行,而不管右侧是否匹配。如果未找到匹配项,则该行将以右侧的列的NULL值进行扩展。 The manual:

LEFT OUTER JOIN

首先,内部联接进行。然后,对于T1中不满足与T2中的任何行的连接条件的每一行,在T2的列中添加具有空值的连接行 。因此,连接表 对于T1中的每一行总是至少有一行。

如果然后在右侧申请表上的列的WHERE条件,你会使效果强行转换LEFT JOIN像一个普通JOIN工作,只是更昂贵,由于更复杂的查询计划。

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

如上所述模糊查询,误导性为LEFT JOIN,使得查询计划者的工作更加困难,对于读者来说会造成误导,并且通常会提示查询逻辑中的错误。从这个引起的问题

很多相关答案:

等等

+0

如果真的“更贵”?现代查询计划人员 - 授予的,我主要使用SQL Server - 给我留下了深刻的印象。 – user2864740

+3

如果它是或不是更昂贵,它会有什么不同。如果你要说表X上的值应该是某种东西(非空值),为什么要用表X的外连接?如果有的话,不要仅仅因为它没有意义就这样做。 –

+0

@ user2864740:在简单的情况下它并不重要。尽管如此,它使得查询优化器的工作在复杂情况下变得更加困难。但正如布赖恩所评论的:不要这样做。这对人类读者来说也很令人困惑。 –