fin*_*ayt 4 arrays postgresql aggregate-functions multidimensional-array
我有一个包含整数数组的表.
我想创建一个聚合函数,它将返回一个包含所有行的二维数组.然后它被传递给plr它做一些数学.
我有:
CREATE OR REPLACE
FUNCTION arrayappend(left int[][], right int[])
RETURNS int[] AS
$BODY$
SELECT $1 || $2 ;
$BODY$
LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)
和:
CREATE AGGREGATE array_sum2 (int[]) (
SFUNC = arrayappend,
STYPE = int[][],
INITCOND = '{}'
);
Run Code Online (Sandbox Code Playgroud)
但是返回类型int[]不是int[][]吗?
如何使用空的二维整数数组初始化聚合?
...附带了聚合函数的附加变体array_agg(),可以将数组聚合到下一个更高维的数组中.看到:
它可以作为array_agg_mult()下面自定义聚合函数的替代品.
使用多态类型,anyarray它适用于所有类型的数组(包括integer[]):
CREATE AGGREGATE array_agg_mult (anyarray) (
SFUNC = array_cat
, STYPE = anyarray
, INITCOND = '{}'
);
Run Code Online (Sandbox Code Playgroud)
正如@Lukas所提供的,arrayappend()不需要自定义功能.内置array_cat()的工作.但是,这并不能解释为什么你的例子失败了,而@Lukas的回答中的那个失败了.相关的区别是@Lukas将数组嵌套到另一个数组层中array[d.a].
您错过了可以声明类型的错误假设int[][].但是你不能:int[][]是同一类型的int[]用于PostgreSQL的类型系统.手册中有关阵列类型的章节解释了:
当前实现也不强制声明的维数.无论尺寸大小或数量如何,特定元素类型的数组都被认为是相同类型的.因此,声明数组大小或维数
CREATE TABLE是简单的文档; 它不会影响运行时行为.
一n维整数数组实际上是n-1PostgreSQL中整数的一维数组.您无法从仅定义基本元素的类型中分辨出来.你必须要求array_dims()具体细节.
展示:
SELECT array_agg_mult(arr1) AS arr2 --> 2-dimensional array
, array_agg_mult(ARRAY[arr1]) AS arr3 --> 3-dimensional array
, array_agg_mult(ARRAY[ARRAY[arr1]]) AS arr4 --> 4-dimensional array
-- etc.
FROM (
VALUES
('{1,2,3}'::int[]) -- = 1-dimensional array
, ('{4,5,6}')
, ('{7,8,9}')
) t(arr1);
Run Code Online (Sandbox Code Playgroud)
要么:
SELECT array_agg(arr2) AS arr3 --> 3-dimensional array
FROM (
VALUES
('{{1,2,3}}'::int[]) -- = 2-dimensional array
,('{{4,5,6}}')
,('{{7,8,9}}')
) t(arr2);
Run Code Online (Sandbox Code Playgroud)
所有结果列的类型相同:( int[]即使包含不同数量的维度).
使用内置的 array_cat 函数是可行的。
CREATE AGGREGATE array_sum2 (int[]) (
SFUNC = array_cat,
STYPE = int[],
INITCOND = '{}'
);
Run Code Online (Sandbox Code Playgroud)
测试:
select array_sum2(array[d.a]) from (select array[1,1,2,3] as a union select array[5,8,13,21] as a) d;
array_sum2
-------------------------
{{1,1,2,3},{5,8,13,21}}
Run Code Online (Sandbox Code Playgroud)