MYSQL5.7+ JSON_ARRAYAGG简单使用
时间:2025-6-4 08:57 作者:wanzi 分类: MYSQL
前言
有这样的要求:根据一个字段group_id
进行分组,得到类似下面的结构:
[
{
"group_id": "001",
"users": [
{"id":1,"name": "user1", "email": "user1@test.com"},
{"id":2,"name": "user2", "email": "user2@test.com"}
]
},
{
"group_id": "002",
"users": [
{"id":10,"name": "user10", "email": "user10@test.com"},
{"id":20,"name": "user2", "email": "user20@test.com"}
]
}
]
根据上面的要求,我们来简单认识下JSON_ARRAYAGG
实现
一、程序代码实现
一般能想到的是程序处理,大概伪代码如下:
class Arr {
public static function groupBy(array $items, string $key, string $vKey): array
{
$groups = [];
foreach ($items as $item) {
if (isset($item[$key])) {
$groupValue = $item[$key];
if (!isset($groups[$groupValue])) {
$groups[$groupValue] = [];
}
$groups[$groupValue][] = $item;
}
}
// 可选:转换为指定结构
$result = [];
foreach ($groups as $groupValue => $groupItems) {
$result[] = [
$key => $groupValue,
$vKey => $groupItems
];
}
return $result;
}
}
$users = DB::query("select id,name,email,group_id from users where group_id <> 0");
$groupUsers = Arr::groupBy($users, 'group_id', 'users')
二、GROUP_CONCAT实现
group_concat 也是我们脑海里面最能想到的一个常用方法,这里我还是对它做个介绍
📌 什么是 GROUP_CONCAT?
GROUP_CONCAT 是 MySQL 提供的一个 聚合函数 ,用于将多行数据中的某一列值合并成一个字符串 。它通常与 GROUP BY 一起使用。
💡 基本语法:
GROUP_CONCAT([DISTINCT] expr [ORDER BY sort_expr] [SEPARATOR sep])
参数说明:
- expr:要拼接的字段或表达式。
- DISTINCT(可选):去重后再拼接。
- ORDER BY(可选):指定拼接顺序。
- SEPARATOR(可选):指定拼接时的分隔符,默认是逗号 ,。
那我们的sql可以这样来:
select
group_id,
GROUP_CONCAT(
CONCAT('{\"id\":', id, ',\"name\":\"', email, '\"}')
SEPARATOR ','
) as users_json
from users where group_id <> 0
group_by group_id
$users = DB::query("...上面的 SQL...");
$groups = array_map(function($item) {
return [
'group_id' => $item['group_id'],
'users' => json_decode($item['users_json'], true)
];
}, $users);
三、JSON_ARRAYAGG实现
📌 什么是 JSON_ARRAYAGG?
JSON_ARRAYAGG 是 MySQL 提供的一个 聚合函数 ,用于将多行数据中的某个表达式或字段值聚合为一个 JSON 数组 。它通常与 GROUP BY 一起使用。这个函数非常适合在查询中生成结构化的 JSON 数据,尤其适用于需要将一对多关系扁平化输出的场景。
🔍 常见用途:
- 将一对多的数据合并成一行,以 JSON 格式展示。
- 避免多次查询或多表连接,提高性能。
- 构建 API 接口时直接返回嵌套结构数据。
- 替代传统 GROUP_CONCAT,避免字符串拼接和分隔符问题。
⚠️ 注意事项:
- JSON_ARRAYAGG 在 MySQL 5.7 及以上版本 中支持。
- 不同于 GROUP_CONCAT,它不需要手动处理转义字符或分隔符。
- 如果你希望对结果排序,可以结合子查询或临时排序字段使用。
那我们的sql可以这样来:
SELECT
group_id,
JSON_ARRAYAGG(JSON_OBJECT('id', id, 'name', email)) AS users_json
FROM users
WHERE group_id <> 0
GROUP BY group_id;
$users = DB::query("...上面的 SQL...");
$groups = array_map(function($item) {
return [
'group_id' => $item['group_id'],
'users' => json_decode($item['users_json'], true)
];
}, $users);