SQL 如何对 JSON 字段进行分组聚合
时间:2026-08-24 | 作者:骑光打字机 | 阅读:0JSON字段无法直接进行GROUP BY操作,必须先将其展开成行,然后再进行分组。在MySQL 8.0+中,可以使用JSON_TABLE函数来展开;在PostgreSQL中,则可以使用jsonb_array_elements()函数配合LATERAL。不过,在使用这两种方法时,都需要确保类型匹配、进行空值过滤,并选择正确的分组维度。
直接回答:JSON字段不能直接GROUP BY,必须先展开成行,再按原始主键或提取字段分组;否则聚合会跨记录混算,结果完全不可信。
MySQL 8.0+ 用 JSON_TABLE 展开后 GROUP BY
与PostgreSQL不同,MySQL中并没有类似的set-returning函数,在这种情况下,JSON_TABLE()就成了唯一可靠的选择。它的作用是将JSON数组“虚拟建表”,但需要注意的是,必须明确地声明路径和列结构。
- 路径写
'$[*]'才能遍历全部元素,写'$[0]'或省略路径会漏数据 COLUMNS中类型必须匹配实际值,比如数组元素是字符串就用TEXT PATH '$',是数字就用INT PATH '$.qty'- 字段存的是字符串(如
"["a","b"]")而非 JSON 类型,JSON_TABLE()会静默返回空——得先CAST(items AS JSON)或确保 DDL 定义为JSON - NULL 或非法 JSON 默认跳过整行,加
LEFT JOIN+COALESCE更稳妥
示例(统计每个订单里各商品数量总和):
SELECT o.id, jt.item_id, SUM(jt.qty) AS total_qty FROM orders o LEFT JOIN JSON_TABLE( o.items, '$[*]' COLUMNS ( item_id INT PATH '$.id', qty INT PATH '$.qty' ) ) AS jt ON TRUE WHERE JSON_VALID(o.items) AND JSON_LENGTH(o.items) > 0 GROUP BY o.id, jt.item_id;
PostgreSQL 用 jsonb_array_elements() 配合 LATERAL
jsonb_array_elements() 是最常用方式,但它只接受 jsonb 类型,且对 NULL 或空数组无容忍——不提前过滤会导致整行丢失。
- 字段是
json类型?必须先转:items::jsonb - 空数组
[]和NULL都要过滤:WHERE items IS NOT NULL AND jsonb_typeof(items) = 'array' AND jsonb_array_length(items) > 0 - 提取字段用
->>'key'(字符串)或(elem->>'qty')::int(转数值),别漏类型转换 - 展开后必须保留原始主键(如
orders.id)用于外层GROUP BY,否则聚合跨订单
示例(统计每单中各状态出现次数):
SELECT o.id, elem->>'status' AS status, COUNT(*) AS cnt FROM orders o, LATERAL jsonb_array_elements(o.items) AS elem WHERE o.items IS NOT NULL AND jsonb_typeof(o.items) = 'array' AND jsonb_array_length(o.items) > 0 GROUP BY o.id, elem->>'status';
聚合前必须确认:你到底想按什么分组?
这是最容易被跳过的逻辑起点。JSON 字段展开后,行数膨胀,分组维度错位会导致结果彻底失真。
- 想“按订单汇总”?
GROUP BY orders.id—— 这是绝大多数场景的正确选择 - 想“按商品 ID 统计全表销量”?那就要
GROUP BY elem->>'id',但得确保所有订单都展开且没丢行 - 原始记录还有其他关键字段(如
order_time、user_id)?它们要么进GROUP BY,要么用MIN()/ANY_VALUE()包裹,否则 PG 会报错 - MySQL 中若需保留非聚合字段又不想写满
GROUP BY,得开sql_mode允许ONLY_FULL_GROUP_BY以外的行为,但不推荐
真正麻烦的不是函数怎么写,而是展开后数据与业务语义的对齐——比如一个订单里两个相同商品对象,是该去重还是累加?这得看业务规则,SQL 本身不会替你判断。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Scalatra 返回 JSON 时最容易踩的几个坑,顺手把正确写法梳理清楚
- 时间:2026-08-25
-
- 怎样用 SQL JSON 函数查询数组中的指定元素
- 时间:2026-08-24
-
- Markdown流中嵌入JSON如何校验?Fluxmend用字符级FSM实现方案
- 时间:2026-08-18
-
- MySQL JSON函数提取与更新嵌套JSON字段值方法
- 时间:2026-08-18
-
- 如何高效动态修改JSON配置文件中的变量值方法
- 时间:2026-08-17
-
- 检测嵌套JSON同级节点重复label值的方法与技巧
- 时间:2026-08-17
-
- Symfony中如何验证单个嵌套JSON对象而不是数组
- 时间:2026-08-17
-
- Go中如何将SQL查询结果映射为多维结构体并序列化JSON
- 时间:2026-08-17
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
