mysql分组后,取每组第一条数据

📅 2026/7/5 21:28:35
mysql分组后,取每组第一条数据
在mysql 5.7之前不包括5.7select * from (select a.* from template_detail a where a.template_id in (3, 4) order by a.id desc) tt group by tt.template_id;但是在mysql 5.7之后包括5.7,这样查询会发现order by 失效是因为mysql 5.7引入了derived_merge什么是derived_mergederived_merge指的是一种查询优化技术作用就是把派生表合并到外部的查询中提高数据检索的效率。这个特性在MySQL5.7版本中被引入可以通过如下SQL语句进行查看/开启/关闭等操作。上面虽然听起来感觉很牛逼的样子但是实际情况是这个新特性不怎么受欢迎容易引起错误。可以在子查询中使用以下函数来进行关闭这个特性可以通过在子查询中使用任何阻止合并的构造来禁用合并尽管这些构造对实现的影响并不明确。 防止合并的构造对于派生表和视图引用是相同的聚合函数 SUM() MIN() MAX() COUNT()等DISTINCTGROUP BYHAVINGLIMITUNION或UNION ALL选择列表中的子查询分配给用户变量仅引用文字值在这种情况下没有基础表所以mysql5.7比较常见的实现方法是select * from (select a.* from template_detail a where a.template_id in (3, 4) order by a.id desc limit 10000) tt group by tt.template_id;这一种也是网上推荐最多的但个人觉得局限性太大不介意用在实战上推荐写法select * from (select distinct(a.id) tid, a.* from template_detail a where a.template_id in (3, 4) order by a.id desc) tt group by tt.template_id;加了distinct(a.id) tid, 后结果正确原因是因为临时表派生表derived table中使用order by且使其生效必须满足三个条件外部查询禁止分组或者聚合外部查询未指定havingHAVING order by外部查询将派生表或者视图作为from句中唯一指定源不满足这三个条件order by会被忽略。一旦外部表使用了group by那么临时表派生表 derived table将不会执行filesort操作即order by 会被忽略所以我在临时表中加了distinct(a.id)。加了之后就相当于关闭了该特性所以也就生效了。或者这样效率更高一点SELECT bb.detail, bb.id,bb.template_id from template_detail bb INNER JOIN ( SELECT MAX(id) id, template_id from template_detail GROUP BY template_id ) as tb on bb.id tb.id