Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL返回结果集为JSON数组?_Json_Postgresql - Fatal编程技术网

PostgreSQL返回结果集为JSON数组?

PostgreSQL返回结果集为JSON数组?,json,postgresql,Json,Postgresql,我希望PostgreSQL将查询结果作为一个JSON数组返回。给定 create table t (a int primary key, b text); insert into t values (1, 'value1'); insert into t values (2, 'value2'); insert into t values (3, 'value3'); 我想要类似的 [{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"

我希望PostgreSQL将查询结果作为一个JSON数组返回。给定

create table t (a int primary key, b text);

insert into t values (1, 'value1');
insert into t values (2, 'value2');
insert into t values (3, 'value3');
我想要类似的

[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]

(实际上,两者都知道会更有用)。我试过一些东西,比如

select row_to_json(row) from (select * from t) row;
select array_agg(row) from (select * from t) row;
select array_to_string(array_agg(row), '') from (select * from t) row;
我觉得我很接近,但不是真的。我是否应该查看除以下内容之外的其他文档

顺便说一下,我对我的想法不太确定。这是一个常见的设计决策吗?我的想法是,当然,我可以将上述3个查询中的第一个查询的结果(例如)在应用程序中稍微处理一下,然后再将其提供给客户机,但如果PostgreSQL可以直接创建最终的JSON对象,则会更简单,因为我仍然没有在我的应用程序中包含任何对JSON库的依赖

TL;博士 对于对象的JSON数组,以及

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t
对于数组的JSON对象

对象列表 本节介绍如何生成对象的JSON数组,并将每一行转换为单个对象。结果如下所示:

[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
{"a":[1,2,3], "b":["value1","value2","value3"]}
9.3及以上
json\u agg
函数会立即生成此结果。它会自动找出如何将输入转换为JSON并将其聚合为数组

SELECT json_agg(t) FROM t
没有
jsonb
(在9.4中引入)版本的
json\u agg
。您可以将行聚合为一个数组,然后将其转换为:

SELECT to_jsonb(array_agg(t)) FROM t
或者将
json\u agg
与强制转换组合:

SELECT json_agg(t)::jsonb FROM t
我的测试表明,首先将它们聚合到一个数组中要快一点。我怀疑这是因为强制转换必须解析整个JSON结果

9.2 9.2没有
json_agg
to_json
函数,因此您需要使用较旧的
数组to_json

SELECT array_to_json(array_agg(t)) FROM t
SELECT row_to_json(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r
您可以选择在查询中包含一个
row\u to\u json
调用:

SELECT array_to_json(array_agg(row_to_json(t))) FROM t
这会将每一行转换为JSON对象,将JSON对象聚合为数组,然后将数组转换为JSON数组

我看不出两者之间有任何显著的性能差异

清单的对象 本节介绍如何生成JSON对象,每个键都是表中的一列,每个值都是该列值的数组。结果如下所示:

[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
{"a":[1,2,3], "b":["value1","value2","value3"]}
9.5及以上 我们可以利用
json\u build\u对象
函数:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t
您还可以聚合列,创建一行,然后将其转换为对象:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r
请注意,为确保对象具有所需的名称,绝对需要对数组进行别名处理

哪一个更清楚是意见的问题。如果使用
json\u build\u object
函数,我强烈建议在一行中放置一个键/值对,以提高可读性

您也可以使用
array\u agg
代替
json\u agg
,但我的测试表明
json\u agg
稍微快一点

没有
json\u build\u对象
函数的
jsonb
版本。您可以聚合为一行并转换:

SELECT to_jsonb(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r
与其他针对此类结果的查询不同,
array\u agg
在使用
to\u jsonb
时似乎要快一点。我怀疑这是由于解析和验证
JSON\u agg
的JSON结果的开销造成的

也可以使用显式强制转换:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )::jsonb
FROM t
根据我的测试,
to_jsonb
版本允许您避免强制转换,并且速度更快;同样,我怀疑这是由于解析和验证结果的开销造成的

9.4和9.3
json\u build\u object
函数是9.5中新增的,因此您必须在以前的版本中聚合并转换为对象:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r

取决于您是想要
json
还是
jsonb

(9.3没有
jsonb

9.2 在9.2中,甚至不存在
to_json
。您必须使用
行到行json

SELECT array_to_json(array_agg(t)) FROM t
SELECT row_to_json(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r
文档 在中查找JSON函数的文档

json\u agg
在页面上

设计 如果性能很重要,请确保根据自己的模式和数据对查询进行基准测试,而不是信任我的测试

它是否是一个好的设计实际上取决于您的具体应用。在可维护性方面,我看不出有什么特别的问题。它简化了你的应用程序代码,意味着在应用程序的这一部分需要维护的内容更少。如果PG能够提供您所需的现成结果,那么我能想到的不使用它的唯一原因就是性能方面的考虑。不要重新发明轮子和一切

空值 聚合函数在零行上运行时通常返回
NULL
。如果这是一种可能性,您可能希望使用
COALESCE
来避免它们。举几个例子:

SELECT COALESCE(json_agg(t), '[]'::json) FROM t


如果您希望从表中选择字段并聚合为数组,也可以将其归功于

SELECT json_agg(json_build_object('data_a',a,
                                  'data_b',b,
))  from t;
结果会来的

 [{'data_a':1,'data_b':'value1'}
  {'data_a':2,'data_b':'value2'}]

PG 9.4现已在beta 1版本中提供,它改进了对JSON的支持,包括二进制I/O。如果您在开发机器上,您可能想查看一下。@Patrick:谢谢,它看起来确实像JSON_object()是9.4中的一个新函数,我会尝试从t中选择JSON_对象(array_agg(t.a),array_agg(t.b)),如果我有它,谢谢你的回答。您启发我找到第二个问题的答案,从t中选择row_to_json(row(array_agg(t.a),array_agg(t.b)),尽管结果以“f1”和“f2”作为标签,而不是a和b。@engineerX我扩展了我的答案。在某些情况下,当内部选择(从t)时,返回NULL而不是空json数组是不可取的返回零行。这是由聚合函数在选择无行时总是返回NULL引起的,可通过coalesce解决:array_to_json(coalesce(array_agg(t),array[]::record[])。您可以使用
to_json
而不是
row_to_json
array_to_json
“没有jsonb(在9.4中引入