【问题标题】:UNNEST a composite array into rows and columns in Postgres在 Postgres 中将复合数组 UNNEST 成行和列
【发布时间】:2020-08-23 23:55:25
【问题描述】:

Postgres 11.7.

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

select
unnest(array[

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

              ]) as item_list

这就是我想要的:

item_name               item_id  
Red Large Special       1
Blue Small              5
Green Medium Special   87

这是我得到的:

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

我认为我需要一个列规范列表,如下所示:

select * from
unnest(array[

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

              ]) AS item_list(item_name citext, item_id int4)

我得到的是:

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)

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

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

这是对的:

item_name             item_id
Red Large Special     1
Blue Small            5
Green Medium Special  87

有没有办法在不声明类型的情况下获得相同的结果?我正在寻找一种可以即时定义类型的解决方案。我很确定我过去在 Postgres 中做过这个,但也许是用 JSONB?

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

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

【问题讨论】:

    标签: postgresql unnest


    【解决方案1】:

    我能想到的一种方法,就是把它转成jsonb数组:

    select item ->> 'f1' as item_name, 
           (item ->> 'f2')::int as item_id 
    from jsonb_array_elements(to_jsonb(array[
                     ('Red Large Special',     1),
                     ('Blue Small',            5),
                     ('Green Medium Special', 87)
                  ])) t(item)
    

    【讨论】:

      【解决方案2】:

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

      # select * from
      unnest(array[
                       ('Red Large Special'::citext,    1),
                       ('Blue Small'::citext,        5),
                       ('Green Medium Special'::citext, 87)
                    ]) AS item_list(item_name citext, item_id int4);
      ┌──────────────────────┬─────────┐
      │      item_name       │ item_id │
      ├──────────────────────┼─────────┤
      │ Red Large Special    │       1 │
      │ Blue Small           │       5 │
      │ Green Medium Special │      87 │
      └──────────────────────┴─────────┘
      

      【讨论】:

      • "因为字符串常量实际上具有未知类型" - 这是我不太喜欢(也不理解)Postgres 的事情之一 :(跨度>
      • @a_horse_with_no_name 也许这个功能的优点多于缺点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 2021-06-18
      • 2020-09-07
      • 1970-01-01
      相关资源
      最近更新 更多