4

我知道这里和互联网上已经创建了很多关于这个主题的主题。但我真的无法得到关于这两个陈述之间差异的最后一点!我的意思是,尝试和尝试我可以通过查询达到我需要的所有结果,但我真的无法完全控制刀!

我认为自己是一个非常优秀的程序员和一个非常优秀的 SQL-ista,对此我感到有点羞愧......

这是一个例子:

  • 我有一个包含网站页面的表格(“web_page”)
  • 带有类别(“类别”)的表格。
  • 一个类别可以包含一个或多个页面,反之则不行
  • 一个类别可能根本不包含任何页面
  • 页面可以在网站中可见或不可见

因此,如果我想显示所有类别及其页面,我的意思是有页面和没有页面的两个类别,我必须执行以下操作:

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 的类别...但是为什么呢?

这只是一个例子......我想永远理解这种差异!

谢谢你。

4

3 回答 3

4

要使查询按预期工作,请将条件放入ON子句中:

FROM category
LEFT JOIN web_page ON web_page.category_id = category 
   and web_page.active = "Y"

这样做的原因是(对于大多数数据库,但不是全部)该子句在加入WHERE过滤行。如果加入没有导致网页行加入(因为该类别没有网页),那么网页的所有列都是,并且任何值(如)与 a 的比较都是假的,所以那些非- 加入行将被过滤掉。null"Y"null

但是,通过将条件移动到ON子句中,条件在连接时执行,因此您只连接的行active = "Y",但如果没有任何这样的行,您只会得到左连接null网页。

这个版本的查询实际上是在说:“给我所有类别及其活动网页(如果有的话)”

请注意,我说的是“大多数数据库”......例如 mysql 足够聪明,可以理解您正在尝试做什么,并且如果在 mysql 上运行,您的查询将按预期工作。

于 2012-07-04T13:04:51.007 回答
1

发生这种情况是因为 SQL 正在分阶段处理:

  1. FROM子句(所有连接都在这里);
  2. WHERE条款;
  3. GROUP BY条款;
  4. 窗口函数(虽然与 MySQL 无关);
  5. ORDER BY条款。

所以这真的很重要,如果你想过滤web_page.active='Y'或者你想加入相同的条件。在前一种情况下,连接完成,您只需过滤掉结果,将您OUTER的连接转换为INNER一个。在后一种情况下,您将获得所需的结果,因为不匹配的行将导致NULL对应列的值。

于 2012-07-04T13:08:44.713 回答
0

试图帮助你理解部分。

考虑是 SQL 语言的一个方面,当在 中指定条件时LEFT JOIN,它适用于查找要匹配的记录。当在底部的 WHERE 子句中指定条件时,它适用于所有记录 - 在连接发生之后。如您所见,这具有将 更改LEFT JOIN为 an的意外副作用。INNER JOIN

您可以通过执行以下WHERE子句来解决此问题:

WHERE COALESCE(web_page.active,"Y") = "Y"

但这并不能保证得到相同的结果,因此正确的做法是将该标准保留ONJOIN.

于 2012-07-04T13:09:54.627 回答