mysql取出每个分组中最新的记录
2016-08-30 14:52
387 查看
原文:深度分析mysql GROUP BY 与 ORDER BY、mysql取出每个分组中最新的记录、mysql 分组取最新的一条记录(整条记录)
我现在需要取出每个分类中最新的内容
select * from test group by category_id order by
结果如下
明显。这不是我想要的数据,原因是msyql已经的执行顺序是:
写的顺序:select … from… where…. group by… having… order by..
执行顺序:from… where…group by… having…. select … order by…
所以在order by拿到的结果里已经是分组的完的最后结果。
由from到where的结果如下的内容:
到group by时就得到了根据category_id分出来的多个小组
到了select的时候,只从上面的每个组里取第一条信息结果会如下
即使order by也只是从上面的结果里进行排序。并不是每个分类的最新信息。
group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
作用:将要连接的字段按照排序字段的顺序用分隔符连起来显示,默认分隔符是”,”。
如:
按照时间排序将id连接起来,第一个一定是时间最新的。
②substring_index
substring_index(str,delim,count),str:要处理的字符串、delim:分隔符、count:计数
例子:
结果是:www
结果是:www.test
结果为:test.com
也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容,相反,如果是负数,那么就是从右边开始数,第N个分隔符右边的所有内容。
③解析
GROUP_CONCAT将group by 后的id排序后连接起来,SUBSTRING_INDEX取得每行(每个分类)的第一个。
连表,选择出每个分类的id和最大时间作为一个临时表,然后原表和临时表连接,条件是分类id和时间相等。
1、建表、插入测试数据
CREATE TABLE `test` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL, `category_id` tinyint(3) unsigned NOT NULL DEFAULT '0', `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; insert into `test`(`id`,`name`,`category_id`,`date`) values (1,'aaa',1,'2010-06-10 19:14:37'),(2,'bbb',2,'2010-06-10 19:14:55'),(3,'ccc',1,'2010-06-10 19:16:02'),(4,'ddd',1,'2010-06-10 19:16:15'),(5,'eee',2,'2010-06-10 19:16:35');
我现在需要取出每个分类中最新的内容
select * from test group by category_id order by
date
结果如下
明显。这不是我想要的数据,原因是msyql已经的执行顺序是:
写的顺序:select … from… where…. group by… having… order by..
执行顺序:from… where…group by… having…. select … order by…
所以在order by拿到的结果里已经是分组的完的最后结果。
由from到where的结果如下的内容:
到group by时就得到了根据category_id分出来的多个小组
到了select的时候,只从上面的每个组里取第一条信息结果会如下
即使order by也只是从上面的结果里进行排序。并不是每个分类的最新信息。
2、方法
下面介绍两种方法,一种是通过子查询,一种是通过group_concat函数来实现。2.1 子查询解决方案
先将数据按照日期倒序排序(日期最新的在最前面),然后在group,这样每个分类的第一条肯定是日期最新的。select * from (select * from `test` order by `date` desc) `temp` group by category_id order by `date` desc
2.2 通过group_concat函数
①group_concat函数group_concat( [DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator ‘分隔符’] )
作用:将要连接的字段按照排序字段的顺序用分隔符连起来显示,默认分隔符是”,”。
如:
select group_concat(id order bydate
desc) fromtest
group by category_id
按照时间排序将id连接起来,第一个一定是时间最新的。
②substring_index
substring_index(str,delim,count),str:要处理的字符串、delim:分隔符、count:计数
例子:
SELECT SUBSTRING_INDEX('www.test.com','.',1);
结果是:www
SELECT SUBSTRING_INDEX('www.test.com','.',2)
结果是:www.test
SELECT SUBSTRING_INDEX('www.test.com','.',-2);
结果为:test.com
也就是说,如果count是正数,那么就是从左往右数,第N个分隔符的左边的全部内容,相反,如果是负数,那么就是从右边开始数,第N个分隔符右边的所有内容。
③解析
GROUP_CONCAT将group by 后的id排序后连接起来,SUBSTRING_INDEX取得每行(每个分类)的第一个。
SELECT * FROM `test` WHERE id IN(SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY `date` DESC),',',1) FROM `test` GROUP BY category_id ) ORDER BY `date` DESC;
2、3 其他方法
一般id越大的时间越近,可以先选出各个分类最大的id,然后in。SELECT MAX(id) AS id,category_id,MAX(DATE) FROM test GROUP BY category_id 4000 ; SELECT * FROM test WHERE id IN (SELECT MAX(id) FROM test GROUP BY category_id);
连表,选择出每个分类的id和最大时间作为一个临时表,然后原表和临时表连接,条件是分类id和时间相等。
SELECT * FROM test AS a, (SELECT category_id, MAX(DATE) AS `date` FROM test AS b GROUP BY category_id) AS b WHERE a.category_id=b.category_id AND a.date = b.date
相关文章推荐
- mysql取出每个分组中最新的记录
- [MySQL]学习笔记- 用户行为表中,查询每个人的一条最新行为(分组 排序 取时间最大的一条记录)
- MySql中取出每个分组中的前N条记录
- mysql 分组取最新的一条记录(整条记录)
- mysql 分组取最新的一条记录(整条记录) 解决我困扰好多天的问题
- 【记录】T-SQL 分组排序中取出最新数据
- mysql 取每个分组中时间最近的记录
- mysql 分组取最新的一条记录(整条记录)
- MySQL分组查询获取每个学生前n条分数记录(分组查询前n条记录)
- oracle取出每个分组的第一条记录
- mysql分组后获得每个分组记录数
- mysql 读取某个分组最大值,或最新记录的sql
- mysql 分组后取每个组内最新的一条数据
- 如何取出每个分组的第一条记录
- 4000 mysql分组排序取最大、最小、最新、前N条记录
- yii 使用原生sql 查询 以某一字段分组 每个字段取出最新的一条数据
- mysql分组查询取分组后各分组中的最新一条记录
- mysql 分组取最新的一条记录(整条记录)
- 【记录】T-SQL 分组排序中取出最新数据