将数组映射到复合类型到不同的行类型
Mapping array to composite type to a different row type
我想将 GroupCount
的键值对数组映射到仅映射特定键的 GroupsResult
复合类型。
我正在使用 unnest
将数组转换为行,然后使用 3 个单独的 select 语句提取值。
对于如此简单的事情,这感觉像是很多代码。
是否有更简单/更简洁的方法来完成从数组类型到 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
fiddle
简单一点。 :)
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 here
参见:
- Aggregate columns with additional (distinct) filters
细微差别:如果其中一个名称弹出不止一次,我们的原始版本会引发异常,而这只是 return 最小计数。可能是也可能不是您想要的 - 或者如果永远不会出现重复则无关紧要。
对于许多不同的名称,crosstab()
通常更快。参见:
- PostgreSQL Crosstab Query
我想将 GroupCount
的键值对数组映射到仅映射特定键的 GroupsResult
复合类型。
我正在使用 unnest
将数组转换为行,然后使用 3 个单独的 select 语句提取值。
对于如此简单的事情,这感觉像是很多代码。
是否有更简单/更简洁的方法来完成从数组类型到 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
fiddle
简单一点。 :)
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 here
参见:
- Aggregate columns with additional (distinct) filters
细微差别:如果其中一个名称弹出不止一次,我们的原始版本会引发异常,而这只是 return 最小计数。可能是也可能不是您想要的 - 或者如果永远不会出现重复则无关紧要。
对于许多不同的名称,crosstab()
通常更快。参见:
- PostgreSQL Crosstab Query