jsonb_agg必须配合jsonb_build_object才能保留字段结构;直接jsonb_agg(my_column)仅返回值数组,丢失键名;正确用法是先用jsonb_build_object构造对象再聚合。

jsonb_agg 必须配合 jsonb_build_object 才能保留字段结构
直接 jsonb_agg(my_column) 只会把原始值塞进数组,丢掉键名和上下文。比如对 name 和 price 两列分别聚合,结果是 ["Laptop", "Mouse"] 和 [1200.00, 85.00],完全无法对应。
真正要生成带结构的 JSON 对象数组,必须先用 jsonb_build_object 把每行转成对象,再交给 jsonb_agg 收集:
SELECT category, jsonb_agg(jsonb_build_object('name', name, 'price', price)) AS items
FROM products
GROUP BY category;
-
jsonb_build_object参数必须成对出现:第一个是字符串字面量(如'name'),第二个是表达式(如name或COALESCE(price, 0)) - 键不能是列别名,也不能是变量;值支持类型转换,比如
id::text比直接id更稳妥 - 如果某行的
name是NULL,jsonb_build_object仍会输出{"name": null, "price": 1200.00},不会跳过整行
GROUP BY 字段漏写会导致报错或逻辑错误
jsonb_agg() 本身不决定分组逻辑,它只是聚合工具。所有非聚合字段(比如 category、user_id、created_at::date)都必须显式出现在 GROUP BY 中。
常见错误是只写 GROUP BY 1 或漏掉某个字段,PostgreSQL 会直接报错:column "xxx" must appear in the GROUP BY clause。
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
- 不要依赖位置编号(
GROUP BY 1,2),字段顺序一变就失效 - 如果分组字段含
NULL,它们会被归为同一组——这是标准行为,不是 bug - 想按日期分组但字段是
timestamptz?得写GROUP BY created_at::date,否则每秒都算一个组
ORDER BY 必须写在 jsonb_agg() 函数内部
在 SELECT 最外层加 ORDER BY 不会影响 JSON 数组内元素顺序。排序必须嵌在函数里:
SELECT category,
jsonb_agg(jsonb_build_object('name', name, 'price', price)
ORDER BY price DESC) AS items
FROM products
GROUP BY category;
- 函数内的
ORDER BY只作用于当前分组的数据,不影响其他组 - 可以混合排序依据,比如
ORDER BY name, price DESC - 如果排序字段可能为
NULL,建议明确写ORDER BY price DESC NULLS LAST
空数组和 NULL 值需要提前过滤或补默认值
jsonb_agg 对空集合返回 [],不是 NULL;但它不会帮你处理源数据里的空值问题。尤其当输入来自 jsonb_array_elements() 展开时,空数组或 NULL 字段会导致整行丢失。
- 展开前加条件:
WHERE items IS NOT NULL AND items != '[]' - 或者用
COALESCE(items, '[]'::jsonb)避免 LATERAL 关联失败 - 聚合前想剔除含
NULL的记录,用WHERE name IS NOT NULL AND price IS NOT NULL - 想保留记录但把
NULL转成默认值,用COALESCE(name, 'unknown')或NULLIF(price, 0)
最易被忽略的是:jsonb_agg 返回 jsonb 类型,但如果你中间用了 json_build_object,最终结果仍是 json,不能直接用 @> 或 ->> 操作符——必须显式转成 jsonb 或从一开始就用 jsonb_build_object。

















