group_concat配合json_object生成嵌套结构时字段顺序错乱,正确做法是用json_arrayagg替代group_concat,并在子查询内order by排序、用coalesce处理null,确保生成合法json数组且顺序可控。

GROUP_CONCAT 配合 JSON_OBJECT 生成嵌套结构时字段顺序错乱
MySQL 5.7+ 支持 JSON_OBJECT,但直接在 GROUP_CONCAT 里拼接多个 JSON_OBJECT(key, value) 会导致字段顺序不可控——因为 GROUP_CONCAT 默认不保证子查询顺序,且 JSON 键名重复时后出现的会覆盖前一个。
正确做法是先用子查询排序、去重,再聚合:
SELECT JSON_ARRAYAGG(
JSON_OBJECT('id', id, 'name', name, 'score', score)
) AS students
FROM (
SELECT id, name, score
FROM student_scores
ORDER BY score DESC
LIMIT 10
) t;
- 必须用
JSON_ARRAYAGG而非GROUP_CONCAT包裹JSON_OBJECT,否则生成的是字符串而非合法 JSON 数组 -
ORDER BY必须放在子查询内,外层GROUP_CONCAT的ORDER BY对 JSON 构造无效 - 若字段含 NULL,
JSON_OBJECT会忽略该键值对,不是报错也不是填null,需提前用COALESCE处理
PostgreSQL 中 jsonb_agg 与 row_to_json 混用导致类型不匹配
常见错误是把 row_to_json(t.*) 直接丢进 jsonb_agg,结果得到的是 jsonb 数组里套着 json 字符串(类型为 text),而不是统一的 jsonb。
根本原因是 row_to_json 返回 json 类型,而 jsonb_agg 期望输入 jsonb;强制转换即可:
SELECT jsonb_agg( row_to_json(t)::jsonb ) AS items FROM (SELECT id, title, created_at FROM posts WHERE status = 'published') t;
- 漏掉
::jsonb转换,返回值类型是json,后续无法用jsonb_path_query等函数操作 - 若字段含数组或 hstore,
row_to_json会自动转成 JSON,但jsonb_agg不支持直接聚合 record 类型,必须过一遍row_to_json - 性能敏感场景下,避免在
jsonb_agg内写复杂表达式,先在子查询中计算好字段
SQL Server FOR JSON AUTO 生成扁平化结构,但业务需要分组嵌套
FOR JSON AUTO 会按 JOIN 顺序自动生成层级,但一旦有多对一关联(比如一个订单多个商品),就会产生重复订单字段——这不是 bug,是设计如此。真正要的是每个订单一个对象,其 items 字段为数组。
解法是用 FOR JSON PATH + 子查询显式控制结构:
SELECT o.OrderID, o.CustomerID,
(SELECT i.ProductID, i.Quantity, i.Price
FROM OrderItems i
WHERE i.OrderID = o.OrderID
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) AS items
FROM Orders o
FOR JSON PATH, ROOT('orders');
-
WITHOUT_ARRAY_WRAPPER是关键,否则子查询返回带方括号的字符串,外层 JSON 会把它当普通字符串而非数组 - 主查询不能用
AUTO,否则子查询结果会被当作文本字段,失去 JSON 解析能力 - SQL Server 2016+ 才支持
FOR JSON,低版本需用字符串拼接 +REPLACE模拟,极易出错且无类型校验
聚合 JSON 时 NULL 值和空集合的业务含义处理
数据库里没有数据,JSON_ARRAYAGG 返回 NULL;而业务接口往往需要空数组 []。同样,某字段为 NULL 时,JSON_OBJECT 直接跳过该键,但前端可能期望保留 "field": null。
- 用
COALESCE(JSON_ARRAYAGG(...), JSON_ARRAY())把 NULL 转为空数组,MySQL 8.0+ 支持JSON_ARRAY(),旧版只能用'[]'字符串(注意类型不一致) - 要让 NULL 字段显式输出
null,不用JSON_OBJECT(key, value),改用JSON_OBJECT(key, CASE WHEN value IS NULL THEN CAST(NULL AS JSON) ELSE value END) - PostgreSQL 中
jsonb_agg遇空集返回NULL,必须配COALESCE(..., '[]'::jsonb),且右侧字面量必须带类型标注
字段是否可空、空集合代表“无数据”还是“未初始化”,这些语义没法靠 SQL 自动推断,得在写聚合逻辑时就和业务方对齐。不然前端解析失败,排查时才发现后端返回的压根不是 JSON。











