(6条消息) mysql取出每个分组中最新的记录

原文:深度分析mysql GROUP BY 与 ORDER BYmysql取出每个分组中最新的记录mysql 分组取最新的一条记录(整条记录)

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 bydatedesc) fromtestgroup 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;
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  
(0)

相关推荐

  • mysql数据库中利用GROUP

    mysql数据库中利用GROUP_CONCAT)把查询的结果列合并分组显示 效果图 在数据库中group by 一列查询出若干行数据,sql如下: select * from table group ...

  • mysql索引之七:组合索引中选择合适的索引列顺序

    组合索引(concatenated index):由多个列构成的索引,如create index idx_emp on emp(col1, col2, col3, --),则我们称idx_emp索引为 ...

  • (3条消息) MySQL中optimize优化表

    前言 当对MySQL进行大量的增删改操作的时候,很容易产生一些碎片,这些碎片占据着空间,所以可能会出现删除很多数据后,数据文件大小变化不大的现象.当然新插入的数据仍然会利用这些碎片.但过多的碎片,对数 ...

  • (59条消息) 终于讲清楚了nodejs中exports和module.exports的区别

    module.exports 对象是由模块系统创建的.在我们自己写模块的时候,需要在模块最后写好模块接口,声明这个模块对外暴露什么内容,module.exports 提供了暴露接口的方法. 1.返回一 ...

  • (1条消息) Android Studio在Gradle中调用cmd脚本

    Gradle中调用cmd 需要在Gradle编译时,调用某些脚本进行文件操作,比如:头文件更新,或者动态链接库文件的更新等,需要借助脚本文件,并且不需要手动运行,那么如何使用Gradle呢? 如下代码 ...

  • (3条消息) Linux(CentOS7)中安装JDK

    目录 1.下载Oralce JDK 2.卸载Open JDK 2.1.检查一下系统中的jdk版本 2.2.检测jdk安装包 2.3.卸载openjdk 3.上传下载好的Oralce JDK到Linux ...

  • (5条消息) VC++学习之VC中常见问题

    (1)为什么某个类突然在工作区间里面突然看不见了? 只是类隐藏了,打开FILEVIEW,找到隐藏类的头文件,随便敲一下键盘的空格键,类就会在CLASSVIEW中显示了 (2)在基于对话框的程序中,一按 ...

  • (8条消息) MySql数据库常用命令总结(全)

    一.数据库级命令 1. 数据库连接 命令:mysql -h主机地址 -u用户名 -p用户密码 –port=3307 1.找到安装目录bin, 进入该工作目录,键入该命令mysql -u root -p ...

  • (8条消息) MySQL数据库命令

    (8条消息) MySQL数据库命令

  • (8条消息) MySQL基础

    一.连接MySQL 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MySQ: 首先在打开cmd窗口,输入mysql -uroot -p ,然后空格进入MySQL控制台, ...

  • (8条消息) Mysql入门教程

    Mysql5.5 下载地址 百度 Mysql5.5安装教程 https://blog.csdn.net/ryan_woo/article/details/93710357f2148a81a.html ...