在 Postgres 中将复合数组 UNNEST 为行和列

Mor*_*ryx 4 postgresql unnest

Postgres 11.7。

我正在尝试解压一个数组,其中每个项目都有多个元素,并且似乎无法获得正确的语法。我希望有人能指出我所缺少的东西。这是一个例子:

select
unnest(array[

                 ('Red Large Special',     1),
                 ('Blue Small',            5),
                 ('Green Medium Special', 87)

              ]) as item_list

Run Code Online (Sandbox Code Playgroud)

这就是我要的:

item_name               item_id  
Red Large Special       1
Blue Small              5
Green Medium Special   87
Run Code Online (Sandbox Code Playgroud)

这就是我得到的:

base_strings
("Red Large Special",1)
("Blue Small",5)
("Green Medium Special",87)
Run Code Online (Sandbox Code Playgroud)

我相信我需要一个列规格列表,如下所示:

select * from
unnest(array[

                 ('Red Large Special',    1),
                 ('Blue Small',        5),
                 ('Green Medium Special', 87)

              ]) AS item_list(item_name citext, item_id int4)
Run Code Online (Sandbox Code Playgroud)

我得到的是:

ERROR:  function return row and query-specified return row do not match
DETAIL:  Returned type unknown at ordinal position 1, but query expects citext. (Line 9)
Run Code Online (Sandbox Code Playgroud)

如果我正式声明一个自定义的复合类型,我就可以让它工作:

CREATE TYPE item_details AS (
   item_name citext,
   item_id   int4);

select * from
unnest(array[

                 ('Red Large Special',    1),
                 ('Blue Small',        5),
                 ('Green Medium Special', 87)

              ]::item_details[]) as item_list
Run Code Online (Sandbox Code Playgroud)

这是对的:

item_name             item_id
Red Large Special     1
Blue Small            5
Green Medium Special  87
Run Code Online (Sandbox Code Playgroud)

有没有办法在不声明类型的情况下获得相同的结果?我正在寻找一种可以动态定义类型的解决方案。我很确定我过去曾在 Postgres 中完成过此操作,但也许是使用 JSONB 完成的?

我查阅了有关表返回表达式的 Fine Documentation,但无法遵循它。那里没有真正的例子,我无法从语法摘要中推断出来。

https://www.postgresql.org/docs/current/queries-table-expressions.html

跟进

两个很好的答案阻止了我追逐自己的尾巴。在本例中,任务是向多个客户端开放某些功能,因此我可能最好使用 JSON,而不是 Postgres 特定的数组语法。@a_horse_with_no_name 引导我从 JSON 文本开始找到这种代码:

with expanded_data AS (
 select * 
   from json_to_recordset(
        '[
             {"base_text":"Red Large Special","base_id":1},
             {"base_text":"Blue Small","base_id":5},
             {"base_text":"Green Medium Special","base_id":87}
         ]')
      AS unpacked (base_text citext, base_id citext)
 )

select base_text,
       base_id

  from expanded_data
Run Code Online (Sandbox Code Playgroud)

Abe*_*sto 5

因为字符串常量实际上具有unknown类型,所以您需要显式指定所需的类型:

\n\n
# select * from\nunnest(array[\n                 ('Red Large Special'::citext,    1),\n                 ('Blue Small'::citext,        5),\n                 ('Green Medium Special'::citext, 87)\n              ]) AS item_list(item_name citext, item_id int4);\n\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82      item_name       \xe2\x94\x82 item_id \xe2\x94\x82\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xa4\n\xe2\x94\x82 Red Large Special    \xe2\x94\x82       1 \xe2\x94\x82\n\xe2\x94\x82 Blue Small           \xe2\x94\x82       5 \xe2\x94\x82\n\xe2\x94\x82 Green Medium Special \xe2\x94\x82      87 \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n
Run Code Online (Sandbox Code Playgroud)\n