GROUP BY不会删除重复项

时间:2011-08-22 19:10:55

标签: mysql group-by

我有一个我编码的监视列表系统,在用户监视列表的概述中,他们会看到一个记录列表,但是在数据库中列表显示重复,它只显示确切的正确数字。 / p>

我已经尝试GROUP BY watch.watch_idGROUP 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 |
+----------+---------+-----------+------------+

5 个答案:

答案 0 :(得分:23)

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

修改

OP要求澄清。

考虑“视图” - 由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博士所说,“当你选择不做决定时,你仍然做出了选择。”

答案 1 :(得分: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

答案 2 :(得分:2)

我永远不会建议使用SELECT DISTINCT,它在大数据集上确实很慢。

尝试使用EXISTS等内容。

答案 3 :(得分:0)

您按watch.watch_id进行分组,并且您有两个结果,这些结果具有不同的观看ID,因此它们自然不会被分组。

此外,从显示的结果中他们有不同的记录。这似乎是一个完全有效的预期结果。如果您只想选择不同的值,那么您不需要GROUP,但是您想要通过不同的值进行选择。

SELECT DISTINCT() ...

答案 4 :(得分:0)

如果您说您的监视列表是唯一的,则其他表中的一个(或两个)要么(a)有重复项,要么(b)不是您使用的密钥唯一。

要抑制结果中的重复项,请使用DISTINCT作为@Laykes说,或尝试

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

听起来有点像你期望所有3个表的键都是唯一的。如果是这种情况,您只需通过尝试检索不同的值来掩盖SQL的其他问题。