2011-09-22 77 views
4

我需要從OldTable中找到所有不存在於NewTable中的ID
爲什麼這個查詢不能找到id?在一個簡單的SQL查詢中出現「NOT IN」問題

SELECT old_id FROM OldTable WHERE old_id NOT IN (
SELECT id FROM NewTable) 

通過他們的自我,他們返回此

--Returns the id 18571 
SELECT old_id FROM OldTable WHERE old_id = 18571 

--Returns nothing 
SELECT id FROM NewTable WHERE id = 18571 

這裏我錯過了一些東西明顯?

這兩列的類型都是int和主鍵。

解決

id列有空在他們,我只是無知=/

這些作品:

SELECT old_id FROM OldTable EXCEPT SELECT id FROM NewTable 

SELECT * FROM old_table ot WHERE NOT EXISTS (
SELECT * FROM new_table nt WHERE nt.id = ot.old_id) 

這些不工作:

SELECT old_id FROM OldTable LEFT JOIN NewTable ON old_id = id WHERE id IS NULL 

SELECT old_id FROM OldTable WHERE old_id NOT IN (
SELECT id FROM NewTable) 
+4

'SELECT ID FROM NewTable'可能返回一個'NULL'。這將意味着你的查詢不會返回任何結果。 –

+0

是兩列的數據類型完全相同..你是否缺少演員或者可能是一些小格式的調整? – gordatron

+0

子查詢不返回任何空值。這兩個表都在ID列上設置了NOT NULL – Niklas

回答

2
SELECT * FROM old_table ot 
WHERE NOT EXISTS (
    SELECT * FROM new_table nt 
    WHERE nt.new_key = ot.old_key 
    ); 
+0

我認爲這個查詢可行!你能解釋爲什麼,但=)? – Niklas

+1

'NOT IN(subquery)'和'NOT EXISTS(subquery)'之間的行爲差​​異是由於空值的存在。 – onedaywhen

0
SELECT old_id FROM OLDTable WHERE id not in (SELECT id from NewTable); 

您在中和您使用的是第二個查詢

+0

當我將查詢輸入到SO時,由於我的錯誤。 – Niklas

0
select oldtable.id as orginal, newtable.id as new 
from oldtable 
left outer join newtable 
on oldtable.id =newtable.id 
where new is null 

AFAIK ID(我不是專家,第一個查詢條件使用old_id - 檢查我代表;-)左外連接是好的技術這..它會可能執行一個不在和不需要子選擇

@onedaywhen善良指出,這並非總是如此,例如,在SQL Server EXISTS()中可以更高效。

+1

「它會執行一個不在」 - 我注意到你的免責聲明,但是如果你甚至不知道他們正在使用哪個SQL產品,你怎麼知道這一點? – onedaywhen

+0

@onedaywhen非常好的點..只是聽到說,它告訴我,子選擇&不在=壞。這是否取決於產品/引擎? – gordatron

+1

是的,除其他外。 'EXISTS()'對於SQL Server來說是很好的,因爲它*可能*短路,但可能每次都不是最好的。 – onedaywhen

1

我不知道爲什麼你的查詢不會給你想要的結果,但我知道使用NOT IN不是很有效。你會使用連接的更好:

SELECT old_id 
FROM OldTable 
LEFT JOIN NewTable 
    ON old_id = id 
WHERE id IS NULL 
+1

「效率不高」 - 以什麼方式記住你甚至不知道他們正在使用哪個SQL產品? – onedaywhen

+0

你是對的,我假設MySQL(無故)...... –

+0

這是MsSQL。現在標記它。 – Niklas

2

的差異可以歸因於零點的存在。

考慮這兩個簡化查詢,注意到謂詞兩個是NULL = 1其評估,其被不同地通過NOT EXISTSNOT IN分別處理UNKNOWN:因爲NOT IN (subquery)評價爲FALSE

SELECT * 
    FROM OldTable 
WHERE NULL NOT IN (SELECT 1 FROM OldTable); 

SELECT * 
    FROM OldTable 
WHERE NOT EXISTS (SELECT * FROM OldTable WHERE NULL = 1); 

第一返回任何行。

第一個返回所有行,因爲NOT EXISTS (subquery)評估爲TRUE。

結論:避免空值。

+1

他們說列雖然不是空的。我懷疑他們碰到與此處相同的問題http://stackoverflow.com/q/4594733/73226 –

+0

+1原來他們是空的... –

+0

@Martin史密斯:但你是正確的,它可能是一樣的作爲你鏈接到的一個問題,我沒有遇到過自己(這真的應該導致語法錯誤國際海事組織!),所以感謝。 – onedaywhen