`

关于MYSQL group by 分组按时间取最大值的实现方法!

 
阅读更多

类如 有一个帖子的回复表,posts( id , tid , subject , message ,  dateline ) ,

id 为 自动增长字段, tid为该回复的主题帖子的id(外键关联),  subject 为回复标题, message 为回复内容, dateline 为回复时间,用UNIX 时间戳表示,

现在要求 选出 前十个来自不同主题的最新回复


SELECT * FROM posts GROUP BY  tid  LIMIT 10



这样一个sql语句选出来的并非你想要的 最新的回复,而是最早的回复,实际上是某篇主题的第一条回复记录!

也就是说 GROUP BY 语句没有排序,那么怎么才能让 GROUP 按照 dateline 倒序排列呢?加上 order by 子句?

看下面:

SELECT * FROM posts GROUP BY  tid  ORDER BY dateline DESC LIMIT 10


这条语句选出来的结果和上面的完全一样,不过把结果倒序排列 了,而选择出来的每一条记录仍然是上面的记录,原因是 group by 会比 order by 先执行,这样也就没有办法将 group by 之前,也就是在分组之前进行排序了, 有网友会写出下面的sql 语句:


SELECT * FROM posts GROUP BY  tid DESC ORDER BY dateline DESC LIMIT 10



也就是说 在 GROUP BY 的字段 tid 后面加上递减顺序,这样不就可以取得分组时的最后回复了吗?这个语句执行结果会和上面的一模一样,这里加上 DESC 和ASC对执行结果没有任何影响!其实这是一个错误的语句,原因是GROUP BY 之前并没有排序功能,mysql 手册上面说,GROUP BY 时是按照某种顺序排序的,某种顺序到底是什么顺序?其实根本没有顺序,因为按照tid分组,其实也就是说,把tid相等的归纳到一个组,这样想的话,GROUP BY tid DESC 可以认为是在按照 tid 分组的时候,按照tid进行倒序排列,这不扯吗,既然是按照tid分组,当然是tid相等的归到一组,而这时候按照tid倒叙还是升序有个P用!


于 是有网友发明下面的语句:


SELECT * FROM posts GROUP BY  tid , dateline DESC ORDER BY dateline DESC LIMIT 10



心 想这样我就可以在分组前按照  dateline 倒序排列了,其实这个语句并没有起到按照tid分组的作用,原因还是上面的,在group by 字段后加 desc 还是 asc 是错误的写法,而这种写法 网友本意是想 按照 tid 分组,并且在分组的时候按照 dateline排倒序!而实际这句相当于下面的写法:(去掉 GROUP BY 字段后面的 DESC)


SELECT * FROM posts GROUP BY  tid , dateline ORDER BY dateline DESC LIMIT 10


也就是说,按照 tid 和 dateline 联合分组,只有在记录tid和dateline 同时相等的时候才归纳到一组,这显然不可能,因为 dateline 时间线基本上是唯一的!


有人写出下面的语句:


SELECT *,max(dateline) as max_line FROM posts GROUP BY  tid ORDER BY dateline DESC LIMIT 10


这条语句的没错是选出了最大发布时间,但是你可 以对比一下 dateline 和 max_dateline 并不相等!(可能有相当的情况,就是分组的目标记录只有一条的时候!)


为 什么呢?原因很简单,这条语句相当于是 在group by 以后选出本组的最大的发布时间!对分组没有起到任何影响!因为SELECT子句是最后执行的!

后来更有网友发明了下面的写法!


SELECT *,max(dateline) as max_line FROM posts GROUP BY  tid HAVING dateline=max(dateline)


ORDER BY dateline DESC LIMIT 10



这条语句的预期结果和想象中的并不相同!因为你会发现,分组的结果 中大量的记录没有了!为什么?因为 HAVING 是在分组的时候执行的,也就说:在分组的时候加上一个这样的条件:选择出来的 dateline 要和 本组最大的dateline 相等,执行的结果和下面的语句相同:


SELECT *,max(dateline) as max_line FROM posts GROUP BY  tid HAVING count(*)=1


ORDER BY dateline DESC LIMIT 10


看 了这条sql语句是不是明白了呢?

dateline=max(dateline) 只有在分组中的记录只有一条的时候才成立,原因很明白吧!只有一条他才会和本组的最大发布时间相等阿,(默认dateline为不重复的值)


原 因还是因为 group by 并没有排序功能,所有的这些排序功能只是错觉,所以你最终选出的 dateline 和max(dateline) 永远不可能相等,除非本组的记录只有一条!GROUP BY 在分组的时候,可能是一个一个来找的,发现有相等的tid,去掉,保留第一个发现的那一条记录,所以找出来的记录永远只是按照默认索引顺序排列的!


那 么说了这么多,到底有没有办法让 group by 执行前分组阿?有的 ,子查询阿!


最简单的 :


SELECT * FROM (SELECT * FROM posts ORDER BY dateline DESC) GROUP BY  tid ORDER BY dateline DESC LIMIT 10



也 有网友利用自连接实现的 ,这样的效率应该比上面的子查询效率高,不过,为了简单明了,就只用这样一种了,GROUP BY没有排序功能,可能是mysql弱智的地方,也许是我还没有发现,

期待高人拍砖!

 

 

以上转之:http://www.alixixi.com/program/a/2011012867346.shtml

 

我在按照作者的思路下解决了该麻烦,非常感谢作者啊!不过还有一点要注意,

 

SELECT * FROM (SELECT * FROM posts ORDER BY dateline DESC) 在这段代码后要为该查询语句起个别名,作表名使用,不然报错!

 

 

完全正确的写法:

SELECT * FROM (SELECT * FROM posts ORDER BY dateline DESC)  BIAOMING GROUP BY  tid ORDER BY dateline DESC LIMIT 10

分享到:
评论

相关推荐

    mysql分组取每组前几条记录(排名) 附group by与order by的研究

    –按某一字段分组取最大(小)值所在行的数据 代码如下: /* 数据如下: nameval memo a 2 a2(a的第二个值) a 1 a1–a的第一个值 a 3 a3:a的第三个值 b 1 b1–b的第一个值 b 3 b3:b的第三个值 b 2 b2b2b2b2 b 4 b4b4 b ...

    mysql获取分组后每组的最大值实例详解

    因此,对于获取分组后每组的最大值,正确的方法是使用`INNER JOIN`结合`GROUP BY`和`MAX`函数。这不仅能确保每个分组只返回一条记录,而且返回的是该分组内分数最高的记录。在实际应用中,要根据数据库的特性和需求...

    Sequelize中用group by进行分组聚合查询

    在SQL中,分组查询是通过`GROUP BY`子句来实现的,它可以将数据按照一个或多个列的值进行分组,通常结合聚合函数一起使用,以便对每个分组执行计算。 1. SQL中的分组查询 在SQL中,使用`GROUP BY`语句进行分组操作...

    使用Group by分组统计.rar

    - `MAX()`: 找到分组内数值列的最大值。 - `MIN()`: 找到分组内数值列的最小值。 - `GROUP_CONCAT()`: MySQL特有的函数,用于将分组内的字符串连接成一个字符串。 3. **多列分组**: - 可以同时对多个列进行...

    mysql获取group by总记录行数的方法

    在MySQL数据库中,当执行`GROUP BY`语句时,通常是为了对数据进行分组并进行聚合计算,如计算每个组的总数、平均值等。然而,标准的`GROUP BY`查询并不直接提供每个组的行数,而是返回每个组的一行数据。如果需要...

    mysql group by用法

    MySQL中的`GROUP BY`语句是用于对数据库中的数据进行分组,以便可以对每个分组执行聚合操作,如计算总和、平均值、最大值、最小值等。这个功能在数据分析和报表生成中非常常见,因为它允许我们按特定字段对数据进行...

    MySQL DQL - 分组查询.md

    ##### 示例4:按列进行分组,并计算每个分组中的最大值 ```sql SELECT column_name, MAX(column_name) FROM table_name GROUP BY column_name; ``` **解析**:这里使用`MAX(column_name)`函数来获取每个分组中`...

    MySQL- 分组查询讲解

    - **MAX()**:找出指定列的最大值。 - **MIN()**:找出指定列的最小值。 例如,如果我们想知道每个客户的总订单金额,可以这样写: ```sql SELECT customer_id, SUM(order_amount) FROM orders GROUP BY ...

    0.5 MySQL分组函数与分组查询

    在本节中,我们将详细介绍 MySQL 中的分组函数和分组查询,包括 SUM、AVG、MAX、MIN 等函数,以及 GROUP BY 语句的使用。 一、分组函数 分组函数是 MySQL 中的一种聚合函数,用于对数据进行聚合和分析。常见的分组...

    mysql group by 对多个字段进行分组操作

    MySQL的GROUP BY语句是数据库查询中用于对数据进行分组和聚合操作的关键部分,它允许我们基于一个或多个字段的值对数据进行汇总。在本文中,我们将深入探讨GROUP BY的基本概念、语法以及如何使用它来处理多字段分组...

    深度分析mysql GROUP BY 与 ORDER BY

    `GROUP BY`语句用于将数据表中的数据按照一个或多个列进行分组,以便对每个组进行聚合操作,如计算平均值(AVG)、总和(SUM)、最大值(MAX)、最小值(MIN)等。例如,如果你有一个包含商品信息和分类ID的表,你...

    MySQL之聚合查询、分组和排序

    MySQL使用`GROUP BY`子句来实现这一功能。 - **基本用法**: - `SELECT column_name, aggregate_function(column_name) FROM table_name GROUP BY column_name;` - 示例:假设我们需要按性别分组并计算每个性别的...

    MYSQL GROUP BY用法详解

    MySQL中的`GROUP BY`语句是用于数据分组的关键语法,它允许你在多个记录中对相同字段值进行聚合。在数据库管理和分析中,`GROUP BY`通常与聚合函数(如`COUNT`, `SUM`, `AVG`, `MAX`, `MIN`)一起使用,帮助我们从...

    深入解析mysql中order by与group by的顺序问题

    在MySQL数据库中,`ORDER BY` 和 `GROUP BY` 是两个非常重要的子句,它们用于对查询结果进行排序和分组。理解它们的执行顺序对于优化SQL查询性能和编写正确的查询至关重要。 首先,我们来详细了解这两个子句的作用...

    MySQL中无GROUP BY情况下直接使用HAVING语句的问题探究

    在MySQL中,`GROUP BY` 和 `HAVING` 通常一起用于聚合查询,用来筛选满足特定条件的分组。然而,当没有 `GROUP BY` 子句时,直接使用 `HAVING` 可能会导致非预期的行为。这个问题的探讨主要集中在 `HAVING` 后面直接...

    mysql group_concat 实现把分组字段写成一行的方法示例

    在MySQL中,`GROUP_CONCAT` 是一个非常实用的聚合函数,它允许你在进行分组查询时,将相同分组内的多个字段值合并为一个单一的字符串,通常用于处理那些需要将多行数据整合到一行的情况。这个函数特别适用于那些需要...

    MySQL聚合函数和分组时,使用Python语言和MySQL连接库示例代码.txt

    - 使用`GROUP BY`子句按部门进行分组。 - 执行SQL语句:`cursor.execute(select_query)`。 5. **获取结果**:使用`cursor.fetchall()`获取查询结果。 6. **处理结果**:遍历查询结果,并打印每个部门及其对应的...

    SQL之分组统计和子查询专题

    其中,IN操作符是判断某个值是否在子查询结果集中 ANY操作符是判断某个值是否等于子查询结果集中的最小值 ALL操作符是判断某个值是否等于子查询结果集中的最大值。 需要注意的是,使用NOT IN操作符时,如果集合范围...

    分组查询GROUP BY的使用与SQL执行顺序的讲解

    1. GROUP BY子句可以包含任意数量的列,这意味着你可以根据多个列进行分组,实现更精细的数据划分。 2. 如果在GROUP BY中指定了多个列,数据会按照最后指定的列进行汇总。 3. GROUP BY中列出的所有列都必须是SELECT...

Global site tag (gtag.js) - Google Analytics