2013-10-10 46 views
2

我想了解的情况以及哪里会影响语句的执行,但没有运气..LEFT JOIN声明与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给出了相同的结果这是很好的,但是当我删除了在那里我得到更多的结果是:

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

Incorrect output

这是为什么?

+0

在结果中添加'u2.email'会让你更清楚地知道你得到的结果:http://sqlfiddle.com/#!2/6a133/52'LEFT JOIN'也返回那些在'ON'子句中有空匹配 –

+1

@MichaelBerkowski谢谢我明白了! :) – user2868631

回答

1

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

A where在外连接表上的条件基本上将外连接重新转换回内连接。

0

对于初学者,您的sqlfiddle与本页面上的代码不符。小问题虽然。

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

0

因为这是一个LEFT JOIN,你会得到来自u1值和空值的行从u2如果ON条款不成立。但是,WHERE子句适用于整个结果集,因此如果u2.id结果为NULL,则不会返回。

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

0

做左加入并从右表中选择没有意义。 如果您使用左连接并应用JOIN子句中的所有条件,则可能会看到意外的结果。 WHERE是在JOIN结果之后应用过滤器,因此除非您的JOIN是INNER,否则JOIN和Where之间的切换条件不相同。 JOIN将提供更多结果。 但如果JOIN是INNER JOIN,那么无论你的条件是什么,你都会得到相同的结果。

在你的例子中,如果你只是删除你在哪里选择所有不同的电子邮件,但从u2。因为你已经离开了连接soem的非匹配的u2行将不会被过滤,因为它们将与WHERE子句一样。

+0

这是一个自我加入,所以我不知道左撇子和右撇子有很大的不同。 –

+1

您使用的是同一个表,但连接类型仍然是LEFT OUTER JOIN。口头上,当我们说selef加入它表明只有一个表参与这个连接,但什么类型的连接仍然取决于你试图达到什么目的。 –