我知道这里创建了许多线程&在互联网上关于这个话题。但我真的无法得到两个声明之间的差异的最后一点!我的意思是,尝试和尝试我可以通过我的查询得到我需要的所有结果,但我真的没有完全控制刀!
我认为自己是一个非常优秀的程序员和非常好的SQL-ista,我对此感到有点惭愧......
以下是一个例子:
因此,如果我想显示所有类别及其页面,我的意思是两个类别都有页面和没有,我必须做这样的事情:
FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id AND web_page.active = "Y" )
因此,如果某个类别没有页面,我会在该类别的记录中看到web_page_id为NULL。
但如果我这样做:
FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id )
...
WHERE web_page.active = "Y"...
我只选择至少有一个web_page的类别......但是为什么?
这只是一个例子......我想永远理解这种差异!
谢谢。
答案 0 :(得分:4)
要使查询按预期工作,请将条件放入ON
子句:
FROM category
LEFT JOIN web_page ON web_page.category_id = category
and web_page.active = "Y"
这是有效的原因(对于大多数数据库,但不是全部)WHERE
子句过滤行 后它们被加入。如果连接不会导致网页行加入(因为该类别没有网页),则网页的所有列都将为null
,并且值的任何比较(如"Y"
})到null
为false,因此这些非连接行将被过滤掉。
但是,通过将条件移动到ON
子句中,条件在连接时执行,以便您只加入行active = "Y"
,但如果没有任何此类行,您只需获取左侧加入null
网页。
这个版本的查询真的在说:“给我所有类别及其活动网页(如果有的话)”
请注意,我说“大多数数据库”...例如,mysql足够聪明,可以理解你要做的事情,如果在mysql上运行,你的查询将按预期工作。
答案 1 :(得分:1)
这是因为SQL正在分阶段处理:
FROM
子句(所有联接都在这里); WHERE
条款; GROUP BY
条款; ORDER BY
条款。所以这非常重要,如果你想在web_page.active='Y'
上过滤,或者想要加入,条件相同。在前一种情况下,加入已完成,您只需过滤掉结果,将OUTER
加入转换为INNER
加入。在后一种情况下,您将获得所需的结果,因为不匹配的行将导致相应列的NULL
值。
答案 2 :(得分:0)
尝试帮助您理解部分。
考虑是SQL语言的一个方面,当在LEFT JOIN
中指定条件时,它适用于查找要匹配的记录。
在底部的WHERE子句中指定条件时,它适用于所有记录 - 在发生连接之后。这会产生意想不到的副作用,如您所见,将LEFT JOIN
更改为INNER JOIN
。
您可以通过执行WHERE
这样的句子来解决这个问题:
WHERE COALESCE(web_page.active,"Y") = "Y"
但这并不是保证同样的结果,所以正确的方法是将该标准保留在ON
的{{1}}条款中。