为什么以下(最后两个)语句返回不同的结果。我几乎100%确定他们'用'来返回相同的结果(有人回忆起过去在SQL Server 6/2000中的情况吗?)。
CREATE TABLE [dbo].[color](
[colorid] [int] NOT NULL,
[title] [varchar](255) NOT NULL
) ON [PRIMARY]
INSERT color SELECT 1,'Red' UNION ALL SELECT 2,'Green' UNION ALL SELECT 3,'Blue'
CREATE TABLE [dbo].[membercolor](
[memberid] [int] NOT NULL,
[colorid] [int] NOT NULL
) ON [PRIMARY]
INSERT membercolor SELECT 10,1 UNION ALL SELECT 10,2 UNION ALL SELECT 10,3 UNION ALL SELECT 11,1 UNION ALL SELECT 11,2 UNION ALL SELECT 12,1
SELECT * FROM color
SELECT * FROM membercolor
-- red, green & blue
SELECT * FROM color a LEFT JOIN membercolor b
ON a.colorid=b.colorid AND b.memberid=11
-- red, green - but why?
SELECT * FROM color a LEFT JOIN membercolor b
ON a.colorid=b.colorid WHERE b.memberid IS NULL OR b.memberid=11
答案 0 :(得分:3)
is null
检查仅适用于colors
完全没有匹配的membercolor
。
如果任何membercolor
匹配,您最终会得到如下结果集:
color blue memberid 8
color blue memberid 9
color blue memberid 10
应用where
子句过滤掉所有蓝色行:
memberid IS NULL OR b.memberid=11
如果没有membercolor
匹配,则结果集如下所示:
color blue memberid NULL
where
子句将允许它通过。
答案 1 :(得分:2)
将FROM子句视为处理的一个独立部分,而不是WHERE子句(从标准的角度来看,每个产品都必须假装它)。
在LEFT JOIN期间,系统将从左表中获取每一行,并尝试在右表中查找匹配项。如果有匹配项,那么它将在输出中为右表中的每个匹配行生成一行。 如果没有匹配,那么它将生成一行,右表中的所有列都设置为NULL。
在您的第一个查询中,确实会发生这种情况。但是在第二个查询中,在FROM子句处理期间,它设法生成一个与JOIN条件匹配的行:
3 Blue 10 3
因此它永远不会为右表中的那些列生成具有NULL值的行。
现在,处理WHERE子句时,您的条件会从最终结果集中排除此行。
正如其他人所说,你可能记得ANSI之前的连接语法,这可能会产生令人惊讶的结果。
答案 2 :(得分:1)
总是这样(至少从2000年开始) - 要知道原因,请查看其他声明:
SELECT * FROM color a LEFT JOIN membercolor b
ON a.colorid=b.colorid
另一方面,您可能想要的是:
SELECT * FROM color a LEFT JOIN membercolor b
ON a.colorid=b.colorid AND b.memberid=11 WHERE b.memberid IS NULL OR b.memberid=11