Sql 左连接和内连接差异。。。永远一次
我知道这里有很多关于这个话题的帖子&在互联网上。但我真的不能得到这两种说法之间差异的最后一点!我的意思是,不断地尝试,我可以通过我的查询获得所有我需要的结果,但我真的不能完全控制这把刀 我认为自己是一个非常好的程序员和一个非常好的SQL ista,对此我感到有点惭愧 下面是一个例子:Sql 左连接和内连接差异。。。永远一次,sql,join,left-join,inner-join,Sql,Join,Left Join,Inner Join,我知道这里有很多关于这个话题的帖子&在互联网上。但我真的不能得到这两种说法之间差异的最后一点!我的意思是,不断地尝试,我可以通过我的查询获得所有我需要的结果,但我真的不能完全控制这把刀 我认为自己是一个非常好的程序员和一个非常好的SQL ista,对此我感到有点惭愧 下面是一个例子: 我有一个包含网站页面的表格(“网页”) 包含类别的表(“类别”) 一个类别可以包含一个或多个页面,但反之亦然 类别可能根本不包含任何页面 网页可以在网站中可见或不可见 因此,如果我想显示所有类别及其页面,我指的
- 我有一个包含网站页面的表格(“网页”)
- 包含类别的表(“类别”)
- 一个类别可以包含一个或多个页面,但反之亦然
- 类别可能根本不包含任何页面
- 网页可以在网站中可见或不可见
FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id AND web_page.active = "Y" )
WHERE COALESCE(web_page.active,"Y") = "Y"
因此,如果一个类别没有页面,我会在该类别的记录中看到web_page_id为NULL
但如果我这样做:
FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id )
...
WHERE web_page.active = "Y"...
我将仅选择至少有一个网页的类别。。。但是为什么呢
这只是一个例子。。。我想永远明白这一次的区别
谢谢。要使您的查询按预期工作,请将该条件放入
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上运行,您的查询将按预期工作。这是因为SQL是分阶段处理的:
来自
子句(所有连接都在这里)李>
其中
条款李>
分组依据
条款李>
orderby
子句因此,如果您想在
web\u page.active='Y'
上进行筛选,或者希望以相同的条件加入,这一点非常重要。在前一种情况下,连接完成,您只需过滤掉结果,将外部
连接转换为内部
连接。在后一种情况下,您将获得所需的结果,因为不匹配的行将导致相应列的NULL
值。试图帮助您理解部分
考虑是SQL语言的一个方面,当在左连接中指定条件时,它将在查找要匹配的记录时应用。
当在底部的WHERE子句中指定了条件时,它将应用于所有记录-在连接发生之后。如您所见,这会产生一个意外的副作用,即将左连接
更改为内部连接
您可以通过这样的WHERE
子句来解决这个问题:
FROM category
LEFT JOIN web_page ON ( web_page.category_id = category.category_id AND web_page.active = "Y" )
WHERE COALESCE(web_page.active,"Y") = "Y"
但事实上,这并不能保证得到相同的结果,因此正确的方法是将该标准保留在JOIN
+1的ON
子句中。谢谢我总是想知道JOIN中的哪一个或在哪里首先工作。