为每一行生成一个 JSON 值数组
Posted
技术标签:
【中文标题】为每一行生成一个 JSON 值数组【英文标题】:Generate a JSON array of values for each row 【发布时间】:2021-07-22 02:32:22 【问题描述】:假设以下 CTE:
with mytable as (
select column1 as foo, column2 as bar, column3 as baz
from (values
('a', 'b', 1),
('c', 'd', 2)
) v
)
使用array_agg()
输出一个值数组:
select
array_agg(v)
from mytable v;
-- "(a,b,1)","(c,d,2)"
但令人惊讶的是(至少对我而言),在此数组上使用 to_json()
会将字段名称恢复为每一行的对象
select
to_json(array_agg(v))
from mytable v;
-- ["foo":"a","bar":"b","baz":1,"foo":"c","bar":"d","baz":2]
我们如何让 PostgreSQL 输出一个数组而不是数组,将每一行呈现为一个值数组?
select
something(v)
from mytable v;
-- [["a", "b", 1],["c", "d", 2]]
【问题讨论】:
【参考方案1】:您可以将一行转换为 json,然后取消嵌套键/值对,然后将值聚合回来:
with mytable (foo, bar, baz) as (
values
('a', 'b', 1),
('c', 'd', 2)
)
select jsonb_agg(x.vals)
from mytable m
cross join lateral (
select jsonb_agg(value order by idx) as vals
from json_each(row_to_json(m)) with ordinality as t(key,value,idx)
) x
如果数组中列值的顺序对您很重要,请务必使用json
转换行。
如果你经常需要这个,你可以把它放到一个函数中。
如果数组中列值的顺序不重要,可以使用 JSON 路径函数:
select jsonb_path_query_array(to_jsonb(m), '$.keyvalue().value')
from mytable m;
【讨论】:
【参考方案2】:除了 a_horse_with_no_name 的答案之外,我刚刚找到了一种方法来实现这一点,假设列名是已知的:
with mytable as (
select column1 as foo, column2 as bar, column3 as baz
from (values
('a', 'b', 1),
('c', 'd', 2)
) v
)
select
to_json(array_agg(x.vals))
from (
select
json_build_array(
v.foo,
v.bar,
v.baz
) as vals
from mytable v
) x
;
-- [["a", "b", 1],["c", "d", 2]]
【讨论】:
以上是关于为每一行生成一个 JSON 值数组的主要内容,如果未能解决你的问题,请参考以下文章