MYSQL 子查询聚合

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: 本文介绍了在 MYSQL 中如何将子查询结果进行多种聚合操作,包括计数、字符串拼接、JSON 数组和 JSON 键值对聚合,满足不同场景下的数据处理需求,提升查询效率与数据表达能力。

一、背景

在上篇文章《mysql 面试题:多值字符串如何联表查询?》分享了如何对字符串做子查询。

最终结果像下面的样子。

css

体验AI代码助手

代码解读

复制代码

select A.c_name, A.c_users, B.c_id, B.c_name 
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users);

+--------+----------+------+--------+
| c_name | c_users  | c_id | c_name |
+--------+----------+------+--------+
| one    | b,c,d,aa | aa   | aa     |
| one    | b,c,d,aa | b    | bb     |
| one    | b,c,d,aa | c    | cc     |
| one    | b,c,d,aa | d    | dd     |
+--------+----------+------+--------+

如果你是一个有经验的程序员,可以一眼发现,前面的几列非常冗余。

于是便有了新的问题:MYSQL 子查询结果如何聚合在一起呢?

二、聚合为计数

如果仅仅需要聚合后的数量,使用 count 函数就可以了。

这个在文章《mysql 的 count(*) 与 count(1)》已经分享,这里就不做过多的介绍了。

这里只罗列下语句与结果。

sql

体验AI代码助手

代码解读

复制代码

mysql> select A.c_name, A.c_users, count(*)  user_count
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users) 
group by c_name;

+--------+----------+------------+
| c_name | c_users  | user_count |
+--------+----------+------------+
| one    | b,c,d,aa |          4 |
+--------+----------+------------+

当然,也有人说可以直接从 c_users 得到 count。

比如需要字符串拆分、去重、统计。

那个是另外的技术了,感兴趣的话你可以想想怎么直接从 A 表得到 用户的个数。

三、聚合为一行一列

MYSQL 中有一个 CONCAT 函数,可以将一行中的多列聚合为一列。

同样的,还有一个 GROUP_CONCAT 函数,可以将多行的内容聚合为一行的一列。

通过这个函数,我们就可以将子查询的内容聚合为 A 表的一列了。

语法:

css

体验AI代码助手

代码解读

复制代码

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val])

语法看起来很复杂,这里少做解释。

diff

体验AI代码助手

代码解读

复制代码

-)DISTINCT 对后面的表达式列表去重
-)ORDER BY 由于输出的是拼接的字符串,有先后顺序,排序规则 -)[ASC | DESC] 升序降序开关
-)[,col_name …] 指定多维度排序
-)SEPARATOR 多行之间的分隔符

最简单的例子如下:

css

体验AI代码助手

代码解读

复制代码

mysql> select A.c_name, A.c_users, GROUP_CONCAT( B.c_name)  user_info
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users) 
group by c_name;

+--------+----------+-------------+
| c_name | c_users  | user_info   |
+--------+----------+-------------+
| one    | b,c,d,aa | aa,bb,cc,dd |
+--------+----------+-------------+

此时可能就有人问:这里只对多行一列聚合了,怎么对多行多列聚合。

大家还记得这一小节的第一句话吗?

MYSQL 中有一个 CONCAT 函数,可以将一行中的多列聚合为一列。

CONCAT 怎么做到将多列聚合,GROUP_CONCAT 就可以用想用的方法做到。

还不明白,看下面的例子就明白了,表达式列表就是要拼接的多列字段。

css

体验AI代码助手

代码解读

复制代码

select A.c_name, A.c_users, GROUP_CONCAT(B.c_id, '|', B.c_name)  user_info
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users) 
group by c_name;

+--------+----------+----------------------+
| c_name | c_users  | user_info            |
+--------+----------+----------------------+
| one    | b,c,d,aa | aa|aa,b|bb,c|cc,d|dd |
+--------+----------+----------------------+

四、聚合为数组

上面介绍了如何将多行多列聚合为一行一列。

但是有小朋友不满意了:

聚合的结果是特殊字符拼接的字符串,对于业务来说一点都不好用。

能不能聚合为结构化的结果呢,比如数组 json。

这么一说,发现还真有函数可以做到。

没错,就是 JSON_ARRAYAGG 。

css

体验AI代码助手

代码解读

复制代码

mysql> select A.c_name, A.c_users, JSON_ARRAYAGG( B.c_name)  user_info
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users) 
group by A.c_name;

+--------+----------+-----------------------+
| c_name | c_users  | user_info             |
+--------+----------+-----------------------+
| one    | b,c,d,aa | ["aa","bb","cc","dd"] |
+--------+----------+-----------------------+

这个转数组 json 很好用,但是很可惜不支持指定排序。

五、聚合为对象

上面聚合为数组只支持聚合多行一列为一行一列。

如果有多行多列的话,该如何操作呢?

查看 MYSQL 的官方文档,发现剩余的函数只剩下一个函数了。

那就是 JSON_OBJECTAGG 。

但是阅读下文档,会发现这个函数只能聚合两列,一列作为 Key,一列作为 Value。

如果有重复的 key,将会只保留最后一个。

css

体验AI代码助手

代码解读

复制代码

mysql> select A.c_name, A.c_users, JSON_OBJECTAGG(B.c_id, B.c_name)  user_info
from A, B 
where A.c_id = 'tk' and FIND_IN_SET(B.c_id, A.c_users) 
group by A.c_name;

+--------+----------+------------------------------------------+
| c_name | c_users  | user_info                                |
+--------+----------+------------------------------------------+
| one    | b,c,d,aa | {"aa":"aa","b":"bb","c":"cc","d":"dd"}   |
+--------+----------+------------------------------------------+

六、最后

可以发现, MYSQL 内置了四个聚合函数。

分别是计数、拼接字符串、JSON 数组、JSON 键值对。

至于更复杂的聚合需求,就需要我们自己想办法实现了。


转载来源:https://juejin.cn/post/7012062664465580039

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
应用服务中间件 网络安全 nginx
Nginx配置WebSocket 【支持wss与ws连接】
Nginx配置WebSocket 【支持wss与ws连接】
11166 1
|
机器学习/深度学习 数据挖掘 Python
时序数据的分类及质心的计算
时序数据的分类及质心的计算
574 0
|
7月前
|
关系型数据库 MySQL Java
《理解MySQL数据库》执行计划EXPLAIN深度解析
本文系统讲解MySQL执行计划(EXPLAIN)在Java开发中的应用,涵盖基础语法、各列深度解析及实战优化案例。通过分析type、key、Extra等关键字段,帮助开发者诊断慢查询、优化索引、提升SQL性能,并结合Spring AOP与JDBC实现执行计划的自动化监控与优化建议,构建高效稳定的数据库访问体系。(239字)
|
10月前
|
人工智能 缓存 监控
MCP零基础学习(6)|与大型语言模型(LLM)的深度融合
本文是MCP系列教程的进阶篇,重点讲解如何将MCP与各类大语言模型深度集成,覆盖本地模型(Ollama、vLLM)和在线服务(OpenAI、DeepSeek)的接入方法,并详解提示词模板设计与上下文管理技巧。通过具体代码示例和架构解析,帮助开发者构建灵活、高效的AI应用系统,实现更智能的模型调度与资源利用。
|
SQL 关系型数据库 MySQL
在 MySQL 中使用子查询
【8月更文挑战第12天】
789 0
在 MySQL 中使用子查询
|
开发框架 Dart 前端开发
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。本文从 Flutter 简介、特点、开发环境搭建、应用架构、组件详解、路由管理、状态管理、与原生代码交互、性能优化、应用发布与部署及未来趋势等方面,全面解析 Flutter 技术,助你掌握这一前沿开发工具。
1326 8
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
459 6
|
存储
Postman 接口测试配置 Pre-request Script
Postman 接口测试配置 Pre-request Script
1038 5
Postman 接口测试配置 Pre-request Script
|
安全 Java 测试技术
阿里开发手册 嵩山版-编程规约 (五)日期时间的规范
《阿里开发手册 嵩山版》的日期时间规范部分提供了关于日期时间处理的强制性和推荐性规约,包括日期格式化、时间获取、避免硬编码日期、处理闰年问题等,以确保程序在时间处理上的准确性和稳定性。
多线程并发之CountDownLatch(闭锁)使用详解
多线程并发之CountDownLatch(闭锁)使用详解
1362 0