You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL中获取返回JSON格式的JOIN查询结果?

如何在PostgreSQL中生成指定结构的JSON查询结果

测试环境准备

先创建测试表并插入数据:

CREATE TABLE backend.product (
id          Integer     NOT NULL,
category        text        NOT NULL,
title           text        NOT NULL,
price           money       NOT NULL
);

CREATE TABLE backend.product_details (
id          Integer     NOT NULL,
type            text        NOT NULL,
description     text        NOT NULL
);

CREATE TABLE backend.shipping (
id          Integer     NOT NULL,
description     text        NOT NULL,
price           money       NOT NULL
);

INSERT INTO backend.product (id, category, title, price) VALUES (1, 'sweatshirts', 'hoodie', '$50.00');
INSERT INTO backend.product_details (id, type, description) VALUES (1, 'color', 'red');
INSERT INTO backend.product_details (id, type, description) VALUES (1, 'color', 'blue');
INSERT INTO backend.product_details (id, type, description) VALUES (1, 'color', 'green');
INSERT INTO backend.product_details (id, type, description) VALUES (1, 'size', 'small');
INSERT INTO backend.product_details (id, type, description) VALUES (1, 'size', 'large');
INSERT INTO backend.shipping (id, description, price) VALUES (1, 'standard box', '$17.05');

原查询问题

原查询返回多行扁平化数据,无法满足嵌套JSON的需求:

SELECT p.id, p.category, p.title, p.price, s.description as shipping_box, s.price as shipping_cost, pd.type, pd.description AS choice
FROM backend.product p, backend.shipping s, backend.product_details pd
WHERE p.id = s.id
AND p.id = 1
AND p.id IN (
    SELECT pd.id
    FROM backend.product_details pd
    WHERE pd.id = 1
    GROUP BY pd.id, pd.type, pd.description
);

期望的JSON结构

[
    {
      "id": 1,
      "category": "sweatshirts",
      "title": "hoodie",
      "price": "$50.00",
      "shipping": { 
          "box": "standard box",
          "cost": "$17.05"
        },
      "choices": [ {
          "color": [ "red", "blue", "green" ],
          "size": [ "small", "large" ]
        }  ]
    }
]

解决方案SQL

使用PostgreSQL的JSON聚合函数直接生成目标结构:

SELECT json_agg(
    json_build_object(
        'id', p.id,
        'category', p.category,
        'title', p.title,
        'price', p.price::text,
        'shipping', json_build_object(
            'box', s.description,
            'cost', s.price::text
        ),
        'choices', array_agg(
            json_object_agg(pd.type, pd.choices)
        )
    )
) AS result
FROM backend.product p
JOIN backend.shipping s ON p.id = s.id
JOIN (
    SELECT 
        id,
        type,
        array_agg(description) AS choices
    FROM backend.product_details
    WHERE id = 1
    GROUP BY id, type
) pd ON p.id = pd.id
WHERE p.id = 1
GROUP BY p.id, p.category, p.title, p.price, s.description, s.price;

关键逻辑说明

  • json_agg():将单行聚合结果打包为最外层的JSON数组
  • json_build_object():构建嵌套JSON对象,对应product基础字段和shipping子结构
  • 子查询中的array_agg():把同一类型下的选项合并为数组(比如将red/blue/green合并为color数组)
  • json_object_agg():将类型和对应选项数组转换为键值对,组成choices内的结构
  • ::text:将money类型转为文本,避免JSON中出现额外类型标识

内容的提问来源于stack exchange,提问作者Pax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 09:45:43