2017-08-29 18 views
2

我想從目錄中選擇一些與兩個表(Table1和Table2)無關的行。選擇不在(...)中的ID有任何限制? - 不在VS不存在

目錄中的行與使用字段idA的表相關。

我使用下面的查詢:

;with CTE(id) AS(
select distinct idA from Table1 
union 
select distinct idA from Table2 
) 
select * from Catalog where IdA NOT IN (select id from CTE) 

非常奇怪的是,該查詢不返回任何結果。

如果我使用下面的查詢去CTE後,會返回一些行

select Id from Catalog where not exists (select 1 from CTE where Catalog.IdA = CTE.Id); 

有誰知道是什麼原因呢? AFAK這兩個查詢都是等價的。

當然,第一個查詢比第二個查詢慢,但這不是很重要。重要的部分是,爲什麼這些查詢不會返回相同的結果?

也許有一點很重要,即表1有超過390萬行 ,但只有139283個不同的值爲idA。 表2只有幾千行

任何幫助或意見可以理解

+3

如果'NOT IN'子查詢返回一個或多個NULL值,則整個結果爲NULL(未知)。未知是不正確的,所以條件不滿足並且沒有行返回。 –

+0

爲了標記@DanGuzman所說的,這就是爲什麼你想要明確你在子查詢中返回的列是什麼......或者使用'exists()' – scsimon

+0

@DanGuzman你是絕對正確的!如果我在CTE的查詢中添加:WHERE IdA不爲空,問題就解決了。如果你添加一個答案,我會接受它 – Ayorus

回答

2

如果一個或多個NULL值由NOT IN子查詢返回的謂詞的結果是未知的,而不是真或假,且行由於條件不滿而退回。最好避免NOT IN使用可爲空的表達式來避免這種非直觀的行爲。

雖然略顯冗長,但相關的NOT EXISTS子查詢將始終返回true或false並避免NULL陷入困境。