我有一个带有整数数组的表。
我想创建一个聚合函数,该函数将返回一个二维数组,其中所有行都在一起。然后将其传递给plr
对其进行一些数学运算。
我有:
CREATE OR REPLACE
FUNCTION arrayappend(left int[][], right int[])
RETURNS int[] AS
$BODY$
SELECT $1 || $2 ;
$BODY$
LANGUAGE SQL;
和:
CREATE AGGREGATE array_sum2 (int[]) (
SFUNC = arrayappend,
STYPE = int[][],
INITCOND = '{}'
);
但是返回类型是
int[]
而不是int[][]
吗?如何使用空的二维整数数组初始化聚合?
最佳答案
Postgres 9.5或更高版本
...附带了聚合函数array_agg()
的其他变体。 The manual:
因此,与下面的自定义聚合函数array_agg_mult()
不完全相同。但是,如果可以的话,请使用它。它更快。
有关的:
Postgres 9.4或更旧
任何数组类型的聚合函数
使用polymorphic type
anyarray
,它适用于所有类型的数组(包括integer[]
):CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
如@Lukas提供的那样,不需要自定义函数
arrayappend()
。内置的 array_cat()
可以完成这项工作。但是,这并不能解释您的示例为何失败,而卢卡斯的答案中的示例仍然有效。相关的区别是Lukas使用array[d.a]
将数组嵌套到另一个数组层中。您可能会误认为可以声明
int[][]
类型。但是您不能:int[][]
与PostgreSQL类型系统的int[]
是类型相同的。 chapter on array types in the manual解释:n
-维整数数组实际上是PostgreSQL中的n-1
-维整数数组。从仅定义基本元素的类型中,您无法分辨出这一点。您必须询问 array_dims()
以获得详细信息。展示:
SELECT array_agg_mult(arr1) AS arr1 --> 1-dim array
, array_agg_mult(ARRAY[arr1]) AS arr2 --> 2-dim array
, array_agg_mult(ARRAY[ARRAY[arr1]]) AS arr3 --> 3-dim array
-- etc.
FROM (
VALUES
('{1,2,3}'::int[]) -- 1-dim array
, ('{4,5,6}')
, ('{7,8,9}')
) t(arr1);
或者:
SELECT array_agg_mult(arr2) AS arr2 --> 2-dim array
, array_agg_mult(ARRAY[arr2]) AS arr3 --> 3-dim array
, array_agg(arr2) AS arr3 --> 3-dim array; superior in Postgres 9.5+
FROM (
VALUES
('{{1,2,3}}'::int[]) -- 2-dim array
,('{{4,5,6}}')
,('{{7,8,9}}')
) t(arr2);
所有产生的列都具有相同的类型:
int[]
(即使包含不同数量的维)。