我是靠谱客的博主 外向鸵鸟,最近开发中收集的这篇文章主要介绍MySQL使用GROUP BY分组时如何留下指定的行,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

假设有一个存储文章信息的数据表(article),结构如下:

字段名说明
id主键ID
author_id作者ID
title文章标题
content文章内容
add_time文章添加时间
edit_time文章上一次编辑时间

作者和文章是一对多的关系,现在需要从这个表里查出每个作者最近编辑过的一篇文章,那么可以怎么写SQL语句呢?

分析

这个查询有两个条件:

  1. 每个作者仅需展示一篇文章
  2. 展示的文章是最新编辑过的那一篇

针对第一个条件,可以使用GROUP BY来实现,但第二个条件就有点棘手了,因为MySQL在分组的时候,具体留下哪一条数据是无法指定的,网上有一些方法是用INNER JOIN来处理,示例:

SELECT a.* FROM article a
INNER JOIN (SELECT MAX(edit_time) FROM article GROUP BY author_id) AS b
ON b.edit_time = a.edit_time

不用JOIN的另一种写法:

SELECT * FROM article WHERE edit_time IN (
SELECT MAX(edit_time) FROM article GROUP BY author_id
)

如果edit_time字段跟文章是一对一关系的话,这种方法是可行的,但在我们这个场景里,明显不是一对一关系,因此这种方法不能使用。

解决方法

方案一:

既然GROUP BY无法指定留下哪一条数据,那么就干脆不用GROUP BY,用子查询来处理就好,语句如下:

SELECT * FROM article a
WHERE id = (SELECT id FROM article WHERE author_id=a.author_id ORDER BY edit_time DESC LIMIT 1)

使用EXPLAIN分析这语句的执行计划,会发现使用到独立子查询(DEPENDENT SUBQUERY),表数据量大的时候会有性能问题,因此不能用在线上业务,平时导数据偶尔使用一下还是没问题的。

方案二:

如果MySQL版本是8.0以上的话,可以使用窗口函数:

SELECT t.* FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY author_id ORDER BY edit_time DESC) AS rank FROM article
) AS t WHERE t.rank <= 1

最后

以上就是外向鸵鸟为你收集整理的MySQL使用GROUP BY分组时如何留下指定的行的全部内容,希望文章能够帮你解决MySQL使用GROUP BY分组时如何留下指定的行所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部