关于sql:选择表作为json数组

Select table as json array

我在PostgreSQL中有三个表:ABC
我想从表A获取一行特定的id,以及来自表BC的所有记录以及匹配的id作为聚合JSON。

例如:

1
2
3
4
5
TABLE A                     TABLE B                TABLE C
---------------------------------------------------------------
id / colum1  / colum2       id/  colum 1          id / column1
1  someValue, somValue      1   someVal1           1   someVal1
                            1   someVal2           1   someVal2

id = 1的预期输出为:

1
2
3
4
a.column1   a.column2       ARRAY_JSON_B              ARRAY_JSON_C      
------------------------------------------------------------------------------
someValue    someValue   [{colum1:'someVal1'},       [{colum1:'someVal1'},
                         {colum1:'someVal2'}]        {colum1:'someVal2'}]


这需要Postgres 9.3或更高版本。

简单的案例

我建议在LATERAL连接中使用更简单的json_agg(),用于此目的:

1
2
3
4
5
SELECT *
FROM   a
LEFT JOIN LATERAL (SELECT json_agg(b) AS array_json_b FROM b WHERE id = a.id) b ON TRUE
LEFT JOIN LATERAL (SELECT json_agg(c) AS array_json_c FROM c WHERE id = a.id) c ON TRUE
WHERE  id = 1;

LEFT JOIN LATERAL ... ON true保持结果中的行在连接的左侧不匹配。细节:

  • LATERAL和PostgreSQL中的子查询有什么区别?

细微差别:此查询返回NULL,其中在bc中找不到匹配,@stas'查询与相关子查询返回空数组。可能重要也可能不重要。

实际答案

问题中的示例排除了b中的冗余id列和结果中的c - 这是有意义的。为此,您不能使用@stas的简单相关子查询。虽然它仍然适用于单个列而不是整行,但它会丢失列名并生成一个简单的数组。此外,它不适用于多个列。

json_object_agg()用于单个选定列(也允许自由选择标记名称):

1
2
3
4
5
6
7
8
9
10
11
SELECT *
FROM   a
LEFT   JOIN LATERAL (
   SELECT json_object_agg('colum1', colum1) AS array_json_b
   FROM   b WHERE id = a.id
   ) b ON TRUE
LEFT   JOIN LATERAL (
   SELECT json_object_agg('colum1', colum1) AS array_json_c
   FROM   c WHERE id = a.id
   ) c ON TRUE
WHERE  id = 1;

或者使用子选择进行任何选择(在此示例中为col1col2):

1
2
3
4
5
6
7
8
9
10
11
SELECT *
FROM   a
LEFT   JOIN LATERAL (
   SELECT json_agg(x) AS array_json_b
   FROM  (SELECT col1, col2 FROM b WHERE id = a.id) x
   ) b ON TRUE
LEFT   JOIN LATERAL (
   SELECT json_agg(x) AS array_json_c
   FROM  (SELECT col1, col2 FROM c WHERE id = a.id) x
   ) c ON TRUE
WHERE  id = 1;

有关:

  • 在SQL中返回JSON对象数组(Postgres)
  • 如何从数据中返回jsonb数组和对象数组?

1
2
3
4
5
6
7
SELECT
        a.*,
        to_json(array(SELECT b FROM b WHERE b.id = a.id)) array_json_b,
        to_json(array(SELECT c FROM c WHERE c.id = a.id)) array_json_c
    FROM a
        WHERE
            a.id = 1;

我希望你的Postgresql版本是9.3或更高版本。有一个聪明的函数to_json可以将任何东西转换为json。因此,我们从b获取所有相关行的数组并进行转换。与c相同。