MySQL 中 Group By 后如何选择记录

问题背景

有一张数据库表,记录了一些抖音视频每小时的播放量与点赞量,每个视频每小时都会产生一条记录。现在需要查出每个视频最新的一条记录,希望通过一条sql语句搞定。第一反应就是对 video_id 进行 Group By ,然后想办法取出每一组中 created_time 最新的那条数据。在最后加 Order By 显然是行不通的,因为 Order By 是对 Group By 的结果进行排序。

误区

关于这种问题,网上有很多错误的解决方法,思路是先通过一个子查询把数据按照 created_time 倒序排序,然后再进行 Group By,sql语句如下:

SELECT * FROM
(SELECT * FROM douyin_official_video WHERE ORDER BY created_time DESC) t
GROUP BY video_id

这个方法的成立需要一个前提,就是MySQL 在 Group By 后是按照当前数据排列顺序选择第一条记录的。

然而我查阅了MySQL 5.7 版本的官方文档

If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. This causes MySQL to accept the preceding query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic, which is probably not what you want. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.

这段话总结一下就是, 在 ONLY_FULL_GROUP_BY 这个配置关闭的情况下,MySQL 从 Group 中选择记录的方式是随意的,无论预先对源数据如何进行 Order By,都不会对选择有任何影响。

ONLY_FULL_GROUP_BY 这个配置决定了能否在 SELECT 后的字段中出现 Group By 后没有的字段。ONLY_FULL_GROUP_BY 为 disabled时,允许SELECT 后的字段中出现 Group By 后没有的字段;ONLY_FULL_GROUP_BY 为 enable 时, 只能 SELECT 在 Group By 后出现的字段。而在大多数情况下,为了减轻程序员编写sql语句的压力,ONLY_FULL_GROUP_BY 都会建议设为 disabled。

我的数据库 ONLY_FULL_GROUP_BY 是设为 disabled的,我跑了上述方法,事实证明这个方法确实是无效的,无论我预先如何排序,从 Group 中选择出来的记录都是 id 最小的那一条。但是我也不能说 Group By 以后就是选择 id 最小的那一条,因为文档中明确说明了是 free to choose,我们无法去做其他猜测。也许在有自增主键的情况下,是取主键最小的那一条,但是这个目前无法百分之百证实。

解决方案

因为在这个表中 created_time 最新也就意味着 id 最大,所以我变通一下,把问题简化为取每个视频中 id 最大的一条记录。这个问题可以通过聚合函数 MAX 先把每个视频的最大 id 查出来,然后在对这些 id 查询记录。sql语句如下:

SELECT * FROM douyin_official_video WHERE id IN 
(SELECT MAX(id) FROM douyin_official_video GROUP BY video_id)

结论

在数据库 ONLY_FULL_GROUP_BY 是 disabled 的情况下:

SELECT * FROM table GROUP BY <字段 1>

随机选择一条

SELECT * FROM (SELECT * FROM table ORDER BY <字段 2>) GROUP BY <字段 1>

随机选择一条,而且子查询里面的 ORDER BY 会被优化掉。

参考资料


文章标题:MySQL 中 Group By 后如何选择记录
文章作者:Ciel Ni
文章链接:http://www.cielni.com/2019/08/17/mysql-group-by-select/
有问题或建议欢迎与我联系讨论,转载或引用希望标明出处,感激不尽!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343