我正在尝试从一个列类型中找出来,该类型汇总了数据类型支持的值。类型之间有多种选择,下面只是一个示例(当然其中一些支持更多的聚合):
uuid count()
text count(), min(), max()
integer count(), min, max(),avg(),sum()
我一直在system catalogs and views中苦苦挣扎,但是没有找到我想要的东西。 (请参阅“四处乱动”。)我戳过pg_type
,pg_aggregate
,pg_operator
等。
有没有一种直接的方法可以从列类型开始并收集所有受支持的聚合?
对于背景,我正在编写一个客户端交叉表代码生成器,当该工具自动阻止您选择不支持的聚合时,UX会更好。我现在已经破解了一些硬编码规则,但是想改进系统。
我们正在使用Postgres 11.4。
答案 0 :(得分:2)
可用的汇总功能的简单列表可以基于pg_proc
,如下所示:
SELECT oid::regprocedure::text AS agg_func_plus_args
FROM pg_proc
WHERE prokind = 'a'
ORDER BY 1;
或具有单独的函数名称和参数:
SELECT proname AS agg_func, pg_get_function_identity_arguments(oid) AS args
FROM pg_proc
WHERE prokind = 'a'
ORDER BY 1, 2;
pg_proc.prokind
替换了Postgres 11中的proisagg
。在Postgres 10或更早的版本中:
...
WHERE proisagg
...
相关:
要获取每种数据类型可用功能的列表(您的问题),请从以下内容开始:
SELECT type_id::regtype::text, array_agg(proname) AS agg_functions
FROM (
SELECT proname, unnest(proargtypes::regtype[])::text AS type_id
FROM pg_proc
WHERE proisagg
ORDER BY 2, 1
) sub
GROUP BY type_id;
db <>提琴here
只需开始。一些参数只是“直接”(非聚合的)(这也是为什么多次列出某些函数的原因-由于这些附加的非聚合列,例如string_agg
)。对于“有序集”和“假设集”聚合,有特殊情况。请参阅其他系统目录pg_aggregate
的aggkind
和aggnumdirectargs
列。 (您可能想排除初学者的特殊情况……)
和 许多 类型具有隐式强制转换为查询列出的类型之一。突出的示例string_agg()
也可以与varchar
一起使用,但仅在上面的text
中列出。您可以使用pg_cast
中的信息来扩展查询,以获取完整图片。
此外,某些聚合适用于pseudo types "any"
,anyarray
等。您需要将每种适用的数据类型都纳入其中。
相同数据类型名称的多个别名的复杂性可以轻松消除,但可以:强制转换为regtype
以获取规范名称。或使用pg_typeof()
返回标准名称。相关:
答案 1 :(得分:2)
伙计,那真是令人惊叹谢谢。在我不知道这一点之前,宇宙的热死就到了。我不得不为PG 11兼容性而调整一条线...说那位没有说他正在使用哪个版本的家伙。我对查询进行了重新整理,使其接近所要查找的内容,并包含了一些存档输出。
with aggregates as (
SELECT pro.proname aggregate_name,
CASE
WHEN array_agg(typ.typname ORDER BY proarg.position) = '{NULL}'::name[] THEN
'{}'::name[]
ELSE
array_agg(typ.typname ORDER BY proarg.position)
END aggregate_types
FROM pg_proc pro
CROSS JOIN LATERAL unnest(pro.proargtypes) WITH ORDINALITY proarg (oid,
position)
LEFT JOIN pg_type typ
ON typ.oid = proarg.oid
WHERE pro. prokind = 'a' -- I needed this for PG 11, I didn't say what version I was using.
GROUP BY pro.oid,
pro.proname
ORDER BY pro.proname),
-- The *super helpful* code above is _way_ past my skill level with Postgres. So, thrashing around a bit to get close to what I'm after.
-- First up, a CTE to sort everything by aggregation and then combine the types.
aggregate_summary as (
select aggregate_name,
array_agg(aggregate_types) as types_array
from aggregates
group by 1
order by 1)
-- Finally, the previous CTE is used to get the details and a count of the types.
select aggregate_name,
cardinality(types_array) as types_count, -- Couldn't get array_length to work here. ¯\_(ツ)_/¯
types_array
from aggregate_summary
limit 5;
还有一点输出:
aggregate_name types_count types_array
array_agg 2 {{anynonarray},{anyarray}}
avg 7 {{int8},{int4},{int2},{numeric},{float4},{float8},{interval}}
bit_and 4 {{int2},{int4},{int8},{bit}}
bit_or 4 {{int2},{int4},{int8},{bit}}
bool_and 1 {{bool}}
仍然在我的愿望清单上
弄清楚如何执行数组(我们现在不使用数组字段,只有几个地方可以使用。那时,我不希望我们尝试在数组标签工具
获取各种类型的所有别名。似乎(?)int8等可以通过pg_attribute以多种方式来传递。例如,时间戳可以从“带时区的时间戳”中返回。
这些结果将由客户端代码使用并进行处理,因此我不需要让Postgres在一个查询中找出所有内容,仅够我完成工作。
无论如何,非常非常感谢。
答案 2 :(得分:1)
有pg_proc
目录表,其中列出了所有功能。 proisagg
列标记聚合函数,而proargtypes
列包含参数类型的OID数组。
例如,要获取具有其参数类型名称的所有聚合函数的列表,可以使用:
SELECT pro.proname aggregationfunctionname,
CASE
WHEN array_agg(typ.typname ORDER BY proarg.position) = '{NULL}'::name[] THEN
'{}'::name[]
ELSE
array_agg(typ.typname ORDER BY proarg.position)
END aggregationfunctionargumenttypes
FROM pg_proc pro
CROSS JOIN LATERAL unnest(pro.proargtypes) WITH ORDINALITY proarg (oid,
position)
LEFT JOIN pg_type typ
ON typ.oid = proarg.oid
WHERE pro.proisagg
GROUP BY pro.oid,
pro.proname
ORDER BY pro.proname;
当然,您可能需要扩展它,例如加入并尊重模式(pg_namespace
)并检查pg_type
中的兼容类型(为此请查看typcategory
列),等等。
编辑:
我忽略了proisagg
在版本11中被删除(我仍然主要使用9.6),其他提到的答案。因此,出于完整性考虑:从版本11开始,将WHERE pro.proisagg
替换为WHERE pro.prokind = 'a'
。
答案 3 :(得分:0)
我一直在讨论建议,并希望根据Erwin的一种脚本发布一种改编:
select type_id::regtype::text as type_name,
array_agg(proname) as aggregate_names
from (
select proname,
unnest(proargtypes::regtype[])::text AS type_id
from pg_proc
where prokind = 'a'
order by 2, 1
) subquery
where type_id in ('"any"', 'bigint', 'boolean','citext','date','double precision','integer','interval','numeric','smallint',
'text','time with time zone','time without time zone','timestamp with time zone','timestamp without time zone')
group by type_id;
这将带回有关where子句中指定的类型的详细信息。这不仅对我当前的工作有用,而且对我的一般理解也很有用。我遇到了一些情况,我必须重新铸造某些东西,例如将整数转换为双精度,以使其能够与聚合一起使用。到目前为止,这几乎是反复试验。如果运行上面的查询(或类似的查询),则从输出中更容易看到需要在类似外观类型之间进行重铸的地方。