2011-08-22 114 views
7

我有一個監視列表系統,我已編碼,在用戶的關注列表中,他們會看到記錄列表,但列表顯示的重複項在數據庫中時只顯示確切,正確的號碼。GROUP BY不會刪除重複記錄

我試過GROUP BY watch.watch_id,GROUP BY rec.record_id,沒有任何類型的組我試過似乎刪除重複。我不確定我做錯了什麼。

SELECT watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 
FROM 
(
    watchlist watch 

    LEFT OUTER JOIN records rec ON rec.record_id = watch.record_id 

    LEFT OUTER JOIN members usr ON rec.user_id = usr.user_id 
) 
WHERE watch.user_id = 1 
GROUP BY watch.watch_id 
LIMIT 0, 25 

該監視列表表看起來像這樣:

+----------+---------+-----------+------------+ 
| watch_id | user_id | record_id | watch_date | 
+----------+---------+-----------+------------+ 
|  13 |  1 |  22 | 1314038274 | 
|  14 |  1 |  25 | 1314038995 | 
+----------+---------+-----------+------------+ 

回答

17

GROUP BY不 「刪除重複項」。 GROUP BY允許聚合。如果您只想將重複的行組合起來,請使用SELECT DISTINCT。

如果您需要合併某些列中重複的行,請使用GROUP BY,但需要指定如何處理其他列。您可以省略它們(通過不在SELECT子句中列出它們)或者將它們聚合(使用SUM,MIN和AVG等函數)。例如:

SELECT watch.watch_id, COUNT(rec.street_number), MAX(watch.watch_date) 
... GROUP by watch.watch_id 

編輯

的任擇議定書要求作出一些澄清。

考慮「視圖」 - 所有由FROM和JOIN和WHERE放在一起的數據 - 稱之爲V.有兩件事情你可能想要做。

首先,你可能有,你要合併完全重複行

a b c 
- - - 
1 2 3 
1 2 3 
3 4 5 

然後只需使用DISTINCT

SELECT DISTINCT * FROM V; 

a b c 
- - - 
1 2 3 
3 4 5 

或者,你可能有部分重複的行你希望結合:

a b c 
- - - 
1 2 3 
1 2 6 
3 4 5 

那些前兩行在某種意義上是「相同的」,但在另一種意義上明顯不同(特別是,它們將由SELECT DISTINCT組合)。你必須決定如何組合它們。您可以丟棄列c不重要:

SELECT DISTINCT a,b FROM V; 

a b 
- - 
1 2 
3 4 

或者您可以對它們執行某種聚合。你可以把它們加起來:

SELECT a,b, SUM(c) "tot" FROM V GROUP BY a,b; 

a b tot 
- - --- 
1 2 9 
3 4 5 

你可以添加挑中的最小值:

SELECT a,b, MIN(c) "first" FROM V GROUP BY a,b; 

a b first 
- - ----- 
1 2 3 
3 4 5 

或者你可以取均值(AVG),標準偏差(STD),任何一幫的其他函數,它們爲c取一堆值並將它們合併爲一個。

什麼不是真正的選擇是什麼都不做。如果你只列出未分組的列,DBMS將會拋出一個錯誤(Oracle做這個 - 正確的選擇,imo),或者隨機選擇一個或多個值(MySQL)。但是作爲博士Peart說:「當你選擇不決定時,你仍然做出了選擇。」

+0

對不起,你可以澄清一些更多的聚合。 – MacMac

+0

我看到一個問題,你如何選擇帶有DISTINCT而不是'DISTINCT *'的列。 – MacMac

+0

重新閱讀。我的答案中已經有一個例子。 – Malvolio

0

您正在按watch.watch_id進行分組,您有兩個結果,其中有不同的手錶ID,因此自然不會進行分組。

此外,從顯示的結果中他們有不同的記錄。這看起來像是一個完全有效的預期結果。如果您試圖只選擇不同的值,那麼您不想使用GROUP,但您希望通過不同的值進行選擇。

SELECT DISTINCT() ...

3

雖然SELECT DISTINCT可能你的情況確實工作,一定要注意,爲什麼你有什麼不工作是很重要的。

您正在選擇不在GROUP BY之外的字段。雖然MySQL 允許這個,但它爲非GROUP BY字段返回的確切行是未定義的。

如果你想用GROUP BY做這個嘗試更多的東西像下面這樣:

SELECT watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 
FROM 
(
    watchlist watch 

    LEFT OUTER JOIN est8_records rec ON rec.record_id = watch.record_id 

    LEFT OUTER JOIN est8_members usr ON rec.user_id = usr.user_id 
) 
WHERE watch.watch_id IN (
SELECT watch_id FROM watch WHERE user_id = 1 
GROUP BY watch.watch_id) 
LIMIT 0, 25 
+0

我得到'這個版本的MySQL還不支持'LIMIT&IN/ALL/ANY/SOME子查詢'。 – MacMac

+0

對不起,我的意思是把它放在子查詢之外。查看更新。 –

0

如果說您的監視表中是唯一的,那麼其他表中的一個(或兩個)或者(a)有重複,或(b)不是您使用的密鑰唯一。

爲了抑制重複你的結果,無論是作爲@Laykes說使用DISTINCT,或嘗試

GROUP BY watch.watch_date, 
     rec.street_number, 
     rec.street_name, 
     rec.city, 
     rec.state, 
     rec.country, 
     usr.username 

這有點聽起來像你期望的所有3個表格,被自己的鑰匙獨特,雖然。如果是這種情況,您只需通過嘗試檢索不同的值來屏蔽SQL的其他一些問題。

1

我絕不會推薦使用SELECT DISTINCT,它在大數據集上真的很慢。

嘗試使用諸如EXISTS之類的東西。