2011-08-22 132 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之类的东西。