我有一个食谱的质量保证状态表,并且想要选择所有“丢弃”记录,包括来自重叠的“完美”状态的信息。但是,我只得到交叉点,并且我想要所有“丢弃”记录。
我想执行左连接,它将为我提供 Recipe_qa 表中的所有“丢弃”行,并与任何“完美”行连接。
select *
from recipe_qa as bad
left join recipe_qa as good on good.id = bad.id
where bad.type = 'discard'
and good.type = 'perfect'
上面的查询返回 id 存在“完美”和“丢弃”记录(24 行)的行。我想要的是一个查询,它将为我提供所有“丢弃”行(76 行),其中要么是“完美”id,要么是没有对应行的 null。
这是一个小提琴:http://sqlfiddle.com/#!2/faa49/4 http://sqlfiddle.com/#!2/faa49/4
我究竟做错了什么?
简而言之,您的 where 子句消除了它们。
使用左(或外)连接时,您必须考虑何时施加数据限制以及何时创建笛卡尔。
假设您想要一个表 (A) 中的所有记录,并且只需要另一个表 (B) 中匹配的记录。当执行连接时,B 中将出现 NULL 值(与 A 不匹配的记录)。对 B 字段添加限制条件(where 子句),实际上会从 A 中删除您想要的记录;因为 where 子句在连接之后执行。这与从 INNER JOIN 开始具有相同的效果! (在这种情况下,good.type = 'perfect'将消除所有bad.type = 'discard'的记录,因为当bad.id不存在good.id时,good.type将为null,而不是'perfect';因此 where 消除了此类记录)
使用外连接时,只需将B表上的限制条件移至连接即可避免这种情况。这样,在施加限制后生成笛卡尔坐标,确保表 A 中的“所有记录”保留所有记录。如果不是在连接上,正如您所看到的,限制是在笛卡尔之后施加的,因此空值被删除,并且您不再获得“所有记录”,因此左连接被否定。就好像您一开始就进行了 INNER join。这就是为什么执行 OR 语句返回 null 且该值也有效,但前提是它是 NOT NULL 列(或 null 类型没有语义含义),正如 LC 在下面的注释中指出的那样。
在这种情况下,good.type 的 where 子句将消除左连接的结果,因此可以将条件添加到连接中,以在生成笛卡尔之前强制进行限制(允许存在空值)
select *
from recipe_qa as bad
left join recipe_qa as good
on good.id = bad.id
and good.type = 'perfect'
where bad.type = 'discard'
http://sqlfiddle.com/#!2/faa49/8/0 http://sqlfiddle.com/#!2/faa49/8/0
或者使用 is null 条件不从左连接中排除记录。这存在以下评论中指出的一些风险。
select *
from recipe_qa as bad
left join recipe_qa as good
on good.id = bad.id
where bad.type = 'discard'
and (good.type = 'perfect' or good.type is null)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)