简体   繁体   English

在左连接中没有从表 A 中获取所有记录

[英]Not getting all records from Table A in left join

I have a table of Quality Assurance statuses for recipes and want to select all 'discard' records, including info from 'perfect' statuses where they overlap.我有一个食谱的质量保证状态表,并希望选择所有“丢弃”记录,包括来自“完美”状态重叠的信息。 However, I'm only getting the intersection and I want all 'discard' records.但是,我只得到交叉点,我想要所有“丢弃”记录。

I want to perform a left join that will give me all 'discard' rows from the recipe_qa table, joined with any 'perfect' rows.我想执行一个左连接,它将为我提供 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'

The query above is returning rows where there is a 'perfect' and a 'discard' record (24 rows) for the id.上面的查询返回的行中有一个“完美”和一个“丢弃”记录(24 行)的 id。 What I want is a query that will give me all the 'discard' rows (76 rows), with either the 'perfect' id or a null where there is no corresponding row.我想要的是一个查询,它会给我所有“丢弃”行(76 行),带有“完美”ID 或没有相应行的空值。

Here's a fiddle: http://sqlfiddle.com/#!2/faa49/4这是一个小提琴: http ://sqlfiddle.com/#!2/ faa49/4

What am I doing wrong?我究竟做错了什么?

Put simply, your where clause eliminates them.简而言之,您的 where 子句消除了它们。

When working with left (or outer) joins you have to consider when the data limit is imposed vs when the Cartesian is created.使用左(或外)连接时,您必须考虑何时施加数据限制与何时创建笛卡尔。

Say you want all records from one table (A) and only those that match in the other (B).假设您需要一个表 (A) 中的所有记录,并且只需要与另一个表 (B) 中匹配的记录。 When the join is executed, NULL values will be present in B (unmatched records to A).执行连接时,B 中将出现 NULL 值(与 A 不匹配的记录)。 Adding a limiting criteria (where clause) against B fields, will in-fact eliminate records you want from A;针对 B 字段添加限制条件(where 子句),实际上会从 A 中消除您想要的记录; as the where clause executes AFTER the join.因为 where 子句在连接之后执行。 This has the same effect as if you started with an INNER JOIN!这与从 INNER JOIN 开始的效果相同! (in this case good.type = 'perfect' will eliminate all those records where bad.type = 'discard' because when good.id doesn't exist for bad.id, good.type will be null, not 'perfect'; thus the where eliminates such records) (在这种情况下,good.type = 'perfect' 将消除所有 bad.type = 'discard' 的记录,因为当 bad.id 不存在 good.id 时,good.type 将为空,而不是 'perfect';因此 where 消除了此类记录)

This situation can be avoided simply by moving the limiting criteria on the B table to the join when using outer joins.这种情况可以通过在使用外连接时将 B 表上的限制条件移动到连接来避免。 This way the Cartesian is generated AFTER the limit has been imposed ensuring the "All Records" from table A remains all records.这样,在施加限制后生成笛卡尔坐标,确保表 A 中的“所有记录”仍然是所有记录。 If not on the join, as you've seen, the limit is imposed after the Cartesian and thus null values are removed, and you no longer get "All Records" thus the LEFT join is negated.如果不是在连接上,如您所见,限制是在笛卡尔之后施加的,因此空值被删除,并且您不再获得“所有记录”,因此 LEFT 连接被否定。 It's as if you were doing an INNER join in the first place.就好像您首先进行了 INNER 连接。 This is why doing an OR statement to return nulls and the value also works but only if it is a NOT NULL column (or type of null has no semantic meaning) as LC points out in comments below.这就是为什么执行 OR 语句以返回空值并且该值也有效,但前提是它是 NOT NULL 列(或空值类型没有语义意义),正如 LC 在下面的评论中指出的那样。

In this case your where clause of good.type is eliminating the results of the left join so either add the criteria to the join which forces the limits before the Cartesian is generated (allowing the nulls to exist)在这种情况下,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

OR use an is null condition to not exclude records from left join.或使用为空条件不从左连接中排除记录。 This has some risks indicted in the below comments.这在下面的评论中有一些风险。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM