2010-02-11 64 views
8

我在查詢工作時遇到了問題,我認爲這應該起作用。它在形式MySQL SELECT NOT IN() - 不相交集?

SELECT DISTINCT a, b, c FROM t1 WHERE NOT IN (SELECT DISTINCT a,b,c FROM t2) AS alias 

但MySQL的扼流圈,其中「IN(」啓動。請問mysql支持這樣的語法嗎?如果沒有,我怎麼能去獲得這些結果?我想找到的(A,B不同的元組,c)表1中不存在於表2中。

回答

12

您應該使用不存在:

SELECT DISTINCT a, b, c FROM t1 WHERE NOT EXISTS (SELECT NULL FROM t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) 

使用NOT IN是不是要做到這一點,即使你只檢查一個鍵的最佳方法。原因在於,如果使用NOT EXISTS,那麼DBMS只需檢查索引是否存在所需列的索引;對於NOT IN,它將不得不讀取實際數據並創建一個完整的結果集,隨後需要對其進行檢查。

使用LEFT JOIN,然後檢查NULL也是一個壞主意,當表很大時,它會很慢,因爲查詢需要進行整個連接,完全讀取這兩個表並隨後丟掉很多它。此外,如果列允許NULL值,則檢查NULL將報告誤報。

+0

你知道嗎?我跑了這個查詢,並且花了很長時間(超過10分鐘),所以我殺了它。然後我爲這兩個表設置臨時表並插入不同的信息。然後我運行了對臨時表的查詢。花了一分四秒。爲什麼不能mysql優化這個查詢呢? – user151841 2010-02-11 19:41:02

+1

說實話,mysql在某些方面相當愚蠢和緩慢。 Oracle,MS SQL和PostgreSQL在許多方面做得更好。當然,如果您將索引添加到表格的列中(如果您還沒有它們),速度也會更快。儘管這會以插入時間爲代價,因爲每次都需要更新索引,但這是每次操作做了多少次,哪個時間更重要。 – wich 2010-02-12 07:33:25

0

據我所知,NOT IN一次只能用於1個字段,並且該字段必須在「WHERE」和 「NOT IN」

(編輯:) 嘗試使用NOT EXISTS:

SELECT a, b, c 
FROM t1 
WHERE NOT EXISTS 
    (SELECT * 
    FROM t2 
    WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) 

此外,a,b和c相等的內部聯接應該爲您提供所有非DISTINCT元組,而LEFT JOIN和WHERE IS NULL子句應該爲您提供DISTINCT子元素,正如Charles在下面提到的那樣。

+0

神聖的上帝,這將使一個噩夢查詢。我只關心a,b或c的值,這取決於其他兩個的值! – user151841 2010-02-11 18:03:15

+0

如何使用連接?所有3個字段的內連接應該返回所有非不同的元組 – froadie 2010-02-11 18:05:06

+0

或者如何使用存在? SELECT a,b,c FROM t1 WHERE NOT EXISTS(SELECT * FROM t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c)不知道這是否完全正確,我還沒有太多的經驗與存在 – froadie 2010-02-11 18:12:19

0

SELECT DISTINCT T1。* FROM T1 LEFT JOIN T2 ON(t1.a = t2.a AND t1.b = T2.B AND t1.c = t2.c)WHERE t2.a IS NULL

+0

這是一個非常糟糕的主意,如果表大,左連接將痛苦地緩慢。你正在做很多工作,閱讀這兩個表,完全創建一個左連接結果集等,這是不必要的。 – wich 2010-02-11 18:35:02

+0

確實。不是明智的表現。 – Charles 2010-02-11 19:53:26

-1

需要在WHERE子句後面添加一個列表並刪除別名。

我用類似的表測試了它,它正在工作。

SELECT DISTINCT a, b, c 
FROM t1 WHERE (a,b,c) 
NOT IN (SELECT DISTINCT a,b,c FROM t2) 

使用MySQLworld分貝:

-- dont include city 1, 2 
SELECT DISTINCT id, name FROM city 
WHERE (id, name) 
NOT IN (SELECT id, name FROM city WHERE ID IN (1,2)) 
+0

使用NOT EXISTS會更好,NOT IN將通過讀取整個表強制執行子查詢的結果集,當您使用NOT EXISTS時,不需要爲子查詢創建結果集,並且如果列索引,NOT EXISTS只會讀取索引。 – wich 2010-02-11 18:46:27

+0

你確定嗎?如果這些列沒有被索引,那麼NOT EXISTS就像沒有被編入索引一樣。 – Yada 2010-02-11 19:12:09

0

好吧,我要回答我的問題,儘管所有的偉大的意見別人都給。

下面是我正在嘗試做的正確語法。

SELECT DISTINCT a, b, c FROM t1 WHERE (a,b,c) NOT IN (SELECT DISTINCT a,b,c FROM t2) 

不能保證它的效率,但我含蓄地把更廣泛的問題是「我該如何表達這種思想在SQL」,而不是「我如何獲得一個特定的結果集」。我知道這對每個刺傷的人都是不公平的,對不起!

+1

根據t2的列a,b和c的定義,這可能是錯誤的!如果它們允許NULL值,那麼NOT IN的結果對於任何這樣的值都將是未知的。不存在*是*表達這一點的正確方式,而不是爲此創建的。 – wich 2010-02-12 07:40:25

+0

太棒了!謝謝。 – user151841 2010-02-12 14:50:32

3

我很難找出執行此查詢的正確方法,即使提供了答案;後來我發現MySQL文檔參考我需要:

SELECT DISTINCT store_type FROM stores WHERE NOT EXISTS (SELECT * FROM cities_stores WHERE cities_stores.store_type = stores.store_type);

的竅門,我不得不換我的大腦周圍使用從子查詢中的第一個查詢參考「商店」表。希望這有助於(或幫助別人,因爲這是一個古老的線程。)

http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html