将数组映射到复合类型到不同的行类型

Mapping array to composite type to a different row type

提问人:Willem D'Haeseleer 提问时间:12/22/2021 最后编辑:Erwin BrandstetterWillem D'Haeseleer 更新时间:12/22/2021 访问量:129

问:

我想将键值对数组映射到仅映射特定键的复合类型。GroupCountGroupsResult

我用来将数组转换为行,然后使用 3 个单独的 select 语句来提取值。
对于如此简单的事情,这感觉就像是很多代码。
unnest

有没有一种更简单/更简洁的方法来进行从数组类型到类型的映射?GroupsResult

create type GroupCount AS (
    Name    text,
    Count   int
);

create type GroupsResult AS (
    Cats  int,
    Dogs  int,
    Birds int
);


WITH unnestedTable AS (WITH resultTable AS (SELECT ARRAY [ ('Cats', 5)::GroupCount, ('Dogs', 2)::GroupCount ] resp)
                    SELECT unnest(resp)::GroupCount t
                    FROM resultTable)
SELECT (
        (SELECT (unnestedTable.t::GroupCount).count FROM unnestedTable WHERE (unnestedTable.t::GroupCount).name = 'Cats'),
        (SELECT (unnestedTable.t::GroupCount).count FROM unnestedTable WHERE (unnestedTable.t::GroupCount).name = 'Dogs'),
        (SELECT (unnestedTable.t::GroupCount).count FROM unnestedTable WHERE (unnestedTable.t::GroupCount).name = 'Birds')
)::GroupsResult

小提琴

http://sqlfiddle.com/#!17/56aa2/1

SQL PostgreSQL 转换 复合类型 聚合过滤器

评论


答:

1赞 Erwin Brandstetter 12/22/2021 #1

简单一点。:)

SELECT (min(u.count) FILTER (WHERE name = 'Cats')
      , min(u.count) FILTER (WHERE name = 'Dogs')
      , min(u.count) FILTER (WHERE name = 'Birds'))::GroupsResult
FROM   unnest('{"(Cats,5)","(Dogs,2)"}'::GroupCount[]) u;

db<>fiddle 在这里

看:

细微的区别:如果其中一个名字多次出现,我们的原版会引发异常,而这只会返回最小计数。可能是也可能不是你想要的 - 或者如果永远不会发生重复,就无关紧要了。

对于许多不同的名称,通常更快。看:crosstab()