簡體   English   中英

在左連接中沒有從表 A 中獲取所有記錄

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

我有一個食譜的質量保證狀態表,並希望選擇所有“丟棄”記錄,包括來自“完美”狀態重疊的信息。 但是,我只得到交叉點,我想要所有“丟棄”記錄。

我想執行一個左連接,它將為我提供 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'

上面的查詢返回的行中有一個“完美”和一個“丟棄”記錄(24 行)的 id。 我想要的是一個查詢,它會給我所有“丟棄”行(76 行),帶有“完美”ID 或沒有相應行的空值。

這是一個小提琴: 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 將為空,而不是 'perfect';因此 where 消除了此類記錄)

這種情況可以通過在使用外連接時將 B 表上的限制條件移動到連接來避免。 這樣,在施加限制后生成笛卡爾坐標,確保表 A 中的“所有記錄”仍然是所有記錄。 如果不是在連接上,如您所見,限制是在笛卡爾之后施加的,因此空值被刪除,並且您不再獲得“所有記錄”,因此 LEFT 連接被否定。 就好像您首先進行了 INNER 連接。 這就是為什么執行 OR 語句以返回空值並且該值也有效,但前提是它是 NOT 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

或使用為空條件不從左連接中排除記錄。 這在下面的評論中有一些風險。

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