2008-12-15 101 views
226

我已經得到了以下兩個SQL表(在MySQL):SQL - 找到一個表中的記錄不存在,在另一

Phone_book 
+----+------+--------------+ 
| id | name | phone_number | 
+----+------+--------------+ 
| 1 | John | 111111111111 | 
+----+------+--------------+ 
| 2 | Jane | 222222222222 | 
+----+------+--------------+ 

Call 
+----+------+--------------+ 
| id | date | phone_number | 
+----+------+--------------+ 
| 1 | 0945 | 111111111111 | 
+----+------+--------------+ 
| 2 | 0950 | 222222222222 | 
+----+------+--------------+ 
| 3 | 1045 | 333333333333 | 
+----+------+--------------+ 

如何找出電話由人,他們的製作phone_number是不是在Phone_book?期望的輸出將是:

Call 
+----+------+--------------+ 
| id | date | phone_number | 
+----+------+--------------+ 
| 3 | 1045 | 333333333333 | 
+----+------+--------------+ 

任何幫助將不勝感激。

回答

307

有幾種不同的方式這樣做的,有不同的效率,這取決於您的查詢優化器有多好,你的兩個表的相對大小:

這是最短的語句,如果可能是最快的電話本是很短:

SELECT * 
FROM Call 
WHERE phone_number NOT IN (SELECT phone_number FROM Phone_book) 

或者(感謝Alterlife

SELECT * 
FROM Call 
WHERE NOT EXISTS 
    (SELECT * 
    FROM Phone_book 
    WHERE Phone_book.phone_number = Call.phone_number) 

或(感謝WOPR)

SELECT * 
FROM Call 
LEFT OUTER JOIN Phone_Book 
    ON (Call.phone_number = Phone_book.phone_number) 
    WHERE Phone_book.phone_number IS NULL 

(忽略,正如其他人所說,它通常是最好的選擇你想要的列,而不是「*」)

+1

避免,使用EXISTS - 該提示是在問題的標題 – annakata 2008-12-15 12:02:11

+16

左外連接可能是最快的,一般情況下,它可以防止重複的執行子查詢。 – WOPR 2008-12-15 21:40:40

+0

不挑剔,但我的建議子查詢返回select 'x'而不是select * Alterlife 2008-12-17 08:36:39

17

下面的代碼會比上面給出的答案多一點效率當處理更大的數據集時。

SELECT * FROM Call WHERE 
NOT EXISTS (SELECT 'x' FROM Phone_book where 
Phone_book.phone_number = Call.phone_number) 
+1

與往常一樣,根據目標數據集查詢性能可以選擇具有最佳性能的查詢。 SQL優化器現在已經足夠好了,以至於性能結果往往令人驚訝。 – 2008-12-15 09:44:33

59
SELECT Call.ID, Call.date, Call.phone_number 
FROM Call 
LEFT OUTER JOIN Phone_Book 
    ON (Call.phone_number=Phone_book.phone_number) 
    WHERE Phone_book.phone_number IS NULL 

應該刪除子查詢,使查詢優化器的工作它的魔力。

另外,請避免使用「SELECT *」,因爲如果有人更改了底層表或視圖(並且效率低下),它可能會破壞您的代碼。

+6

這通常是最有效的方法,因爲它不會在第二張桌子上執行多次傳遞......希望有些人閱讀comemnts。 – Nerdfest 2008-12-15 11:57:27

4

我覺得

SELECT CALL.* FROM CALL LEFT JOIN Phone_book ON 
CALL.id = Phone_book.id WHERE Phone_book.name IS NULL 
3
SELECT DISTINCT Call.id 
FROM Call 
LEFT OUTER JOIN Phone_book USING (id) 
WHERE Phone_book.id IS NULL 

這將返回缺少額外的ID,在你的Phone_book表。

1
SELECT t1.ColumnID, 
CASE 
    WHEN NOT EXISTS(SELECT t2.FieldText 
        FROM Table t2 
        WHERE t2.ColumnID = t1.ColumnID) 
    THEN t1.FieldText 
    ELSE t2.FieldText 
END FieldText  
FROM Table1 t1, Table2 t2 
1
SELECT name, phone_number FROM Call a 
WHERE a.phone_number NOT IN (SELECT b.phone_number FROM Phone_book b) 
0

另外,

select id from call 
minus 
select id from phone_number 
相關問題