关于sql语句,分组后(每组多条数据)取每组xxx最大/小的一条

假设数据库的表如下:

我们需要取每组的每个部门创建时间最早的员工信息

第一种方法

网上提供了一种思路:

SELECT name,MAX(create_time),dept FROM test GROUP BY dept

看似是分组后利用聚合函数MAX取每组的时间最大值,貌似可行,但是实际上会发现MAX和group by各走各的,结果如下:

直接移花接木了可还行。。。

不过通过这种思路改变而成的另外一种思路倒是可行,代码如下:

SELECT * FROM test WHERE create_time in (SELECT MAX(create_time) FROM test GROUP BY dept)

结果如下:

虽然结果是对的,但是一旦数据过多,出现创建时间相同的情况,用 where xxx in ()语句每组可能就会查询到多条信息,我又只想要每组最新的“一条”,而不是多条,那么就需要换一种语句来实现。

第二种方法

于是我想到先用order by去倒叙排列时间,然后利用group by去取每组的第一个不就行了么?代码如下:

SELECT * FROM (SELECT * FROM test ORDER BY create_time DESC) a GROUP BY a.dept

虽然查询结果是一样的,但是这种方法每组只会取最新的"一条"。而不会取多条。

以上的语句可以直接在低版本(我测试时的驱动为com.mysql.jdbc.driver)的mysql中直接使用,但是我在高版本(我测试时的驱动为com.mysql.cj.jdbc.driver)的mysql中发现子查询会被优化器优化掉而失效,所以需要使用以下语句:

SELECT * FROM (SELECT * FROM test HAVING 1 ORDER BY create_time DESC) a GROUP BY a.dept

这里加上having 1或者having 1=1效果是一样的,都是为了防止优化器在优化语句时优化掉了子查询。

第三种方法

直接使用sql中的group_concat函数和SUBSTRING_INDEX函数取得每组对应的唯一id再去用where a.id=id取得对应的数据,具体实现代码就不贴了,有点麻烦,可以根据实际情况自己斟酌。

点赞