使用ON和WHERE的LEFT JOIN语句

时间:2013-10-10 19:59:44

标签: sql

我试图理解ON和WHERE如何影响语句的执行,但没有运气..

我有这个声明给了我预期的结果:

     SELECT  DISTINCT u1.email
     FROM user u1
     LEFT JOIN user u2
     ON u1.email = u2.email
     WHERE u1.id != u2.id

Correct output

交换ON和WHERE给出了相同的结果,但是当我删除WHERE时,我得到更多的结果:

    SELECT  DISTINCT u1.email
    FROM user u1
    LEFT JOIN user u2
    ON u1.email = u2.email
    AND u1.id != u2.id

Incorrect output

为什么?

4 个答案:

答案 0 :(得分:1)

这是因为在第一种情况下,在连接后应用了<{1}}子句,并将删除仅由“外部”连接包含的所有行。删除这些行是因为where表中的email列对于那些行为空,并且与u2的任何比较都会产生未定义,这意味着null子句将丢弃这些行

外连接表上的where条件实际上将您的外连接转回到内连接。

答案 1 :(得分:0)

对于初学者,您的sqlfiddle与此页面上的代码不匹配。虽然是小问题。

简短的回答是这样的:当你添加一个检查左连接标准的where子句时,它基本上使它像一个内连接。

答案 2 :(得分:0)

因为这是LEFT JOIN,如果u1子句不成立,您将获得一行u2的值和ON的NULL。但是,WHERE子句适用于整个结果集,因此如果u2.id变为NULL,则不会返回它。

LEFT JOIN更改为INNER JOIN将解决您的问题。

答案 3 :(得分:0)

执行LEFT连接和从右表中选择没有意义。 如果您使用左连接并在JOIN子句中应用所有条件,您可能会看到意外的结果。在JOIN结果之后应用过滤器,所以除非JOIN是INNER,否则JOIN和Where之间的切换条件不一样。 JOIN会给出更多结果。 但如果JOIN是INNER JOIN,那么无论你的条件在哪里,你都会得到相同的结果。

在您的示例中,如果您只是删除了在哪里选择了所有不同的电子邮件,但是来自u2。并且当你离开时,不匹配的u2行的连接soem将不会像WHERE子句那样被过滤。