1

假设以下 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]]
4

2 回答 2

2

您可以将一行转换为 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;
于 2021-04-28T18:07:15.943 回答
1

除了 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]]
于 2021-04-28T18:12:54.887 回答