2011-04-25 48 views
1

我試圖運行下面的MySQL查詢:SQL查詢不返回唯一結果。我需要使用哪種類型的連接?

SELECT * 
FROM user u 
JOIN user_categories uc ON u.user_id = uc.user_id 
WHERE (uc.category_id = 3 OR uc.category_id = 1) 

目前,它返回:

Joe,Smith,60657,male 
Joe,Smith,60657,male 
Mickey,Mouse,60613,female 
Petter,Pan,60625,male 
Petter,Pan,60625,male 
Donald,Duck,60615,male 

如果用戶屬於兩個類別它目前返回他們的兩倍。無論使用哪種類別,我如何才能在不使用SELECT DISTINCT的情況下僅返回一次用戶?

+0

爲什麼你有「不使用SELECT DISTINCT」的限制? – 2011-04-25 02:25:37

+1

我喜歡遠離SELECT DISTINCT。我認爲這是不好的做法,並且認爲如果需要DISTINCT,則查詢不能正確寫入。 – mike 2011-04-25 17:15:17

回答

6

您需要一個半連接。這可以通過子查詢來實現。

SELECT * 
FROM user u 
WHERE EXISTS(SELECT * 
     FROM user_categories uc 
     WHERE u.user_id = uc.user_id AND 
     uc.category_id IN(1,3)) 

在MySQL子查詢的性能是比較困難的。然而這樣通過DISTINCTGROUP BY一個JOIN和重複去除效果會比較好。

+0

這對我有效。謝謝。 – mike 2011-04-25 17:12:46

0

嘗試使用GROUP BY

SELECT * FROM user u 
JOIN user_categories uc ON u.user_id = uc.user_id 
WHERE uc.category_id = 3 OR uc.category_id = 1 
GROUP BY u.user_id 
+0

這不適用於SELECT *,因爲除user_id以外的所有內容都必須在聚合中。 – 2011-04-25 00:37:24

+1

@Andrew - 不在MySQL中。雖然返回的'uc'記錄是任意的。請參閱http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html – 2011-04-25 00:44:47

+0

謝謝。哎呀!非常不規範,雖然有用。 – 2011-04-25 00:46:14

3

我不知道MySQL的,但在Postgres的你可以將得到更好的性能,從

SELECT * FROM user u 
WHERE u.user_id 
IN (SELECT user_id FROM user_categories uc WHERE uc.category_id IN (1,3)); 

我會半連接的版本預計SELECT DISTINCT運行速度最快,但我學到了我的期望,數據庫性能往往大不相同!

+0

在SQL Server'in'和'exists'中,兩者都會得到相同的計劃,並且比'JOIN'好,然後消除重複。 MySQL有一些問題然而,有一些問題http://stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql/3417190#3417190 – 2011-04-25 00:42:45

+1

有趣。我相信PG根據子查詢WHERE子句的選擇性估計來決定,但我通常會嘗試幾個版本並擊中'EXPLAIN ANALYSE'! – 2011-04-25 00:45:23