mysql分组后,取每组第一条数据
- 工作小总结
- 时间:2021-11-23 00:08
- 5540人已阅读
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
在工作中,有时候我们需要先group by之后,然后在获取group by之后的每组数据。这个时候sql怎么写呢?
需求:
获取每本书的起始章节。比如:book_id为1的书籍的起始章节为:(1,2),book_id为2的起始章节为(1,3),这个时候怎么获取呢?
先看结论:
-- 倒叙 select * from (select distinct(a.id) tid, a.* from publish_book_chapter a where a.book_id in (1, 2) order by a.id desc) tt group by tt.book_id; -- 正序 select * from (select distinct(a.id) tid, a.* from publish_book_chapter a where a.book_id in (1, 2) order by a.id ) tt group by tt.book_id;
思路:先进行排序,然后再进行分组,获取每组的第一条。
Q: 为什么要写distinct(a.id)呢?
A:防止合并的构造(derived_merge);
什么是derived_merge?
derived_merge指的是一种查询优化技术,作用就是把派生表合并到外部的查询中,提高数据检索的效率。这个特性在MySQL5.7版本中被引入,可以通过如下SQL语句进行查看/开启/关闭等操作。
上面虽然听起来感觉很牛逼的样子,但是实际情况是,这个新特性,不怎么受欢迎,容易引起错误。
可以在子查询中使用以下函数来进行关闭这个特性:
可以通过在子查询中使用任何阻止合并的构造来禁用合并,尽管这些构造对实现的影响并不明确。 防止合并的构造对于派生表和视图引用是相同的: 1.聚合函数( SUM() , MIN() , MAX() , COUNT()等) 2.DISTINCT 3.GROUP BY 4.HAVING 5.LIMIT 6.UNION或UNION ALL 7.选择列表中的子查询 8.分配给用户变量 9.仅引用文字值(在这种情况下,没有基础表)
子查询order by失效的场景
一旦外部表使用了group by,那么临时表(派生表 derived table)将不会执行filesort操作(即order by 会被忽略)。之后我使用了limit可以使其生效,原因是因为要使派生表order by生效,派生表可以通过使用group by、limit、having、distinct等等使其生效(方法有好多,详情可看文档https://dev.mysql.com/doc/refman/5.7/en/derived-table-optimization.html)
参考地址:
分组查询取每组最新的数据(order by 和group by使用问题):https://blog.csdn.net/weixin_41715751/article/details/102625795
mysql分组后获取每个组排序后的第一条数据(整行):https://blog.csdn.net/persistencegoing/article/details/92764058
Mysql取分组后的每组第一条数据:
https://www.cnblogs.com/hejw0413/p/12809959.html
来源:https://blog.csdn.net/u013066244/article/details/116461584?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~aggregatepage~first_rank_ecpm_v1~rank_v31_ecpm-2-116461584.pc_agg_new_rank&utm_term=mysql+%E5%88%86%E7%BB%84%E5%90%8E%E6%AF%8F%E7%BB%84limit&spm=1000.2123.3001.4430