函数中的初始数组用于聚合多维数组

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[][]吗?

如何使用空的二维整数数组初始化聚合?

Erw*_*ter 9

Postgres 9.5或更新版本

...附带了聚合函数的附加变体array_agg(),可以将数组聚合到下一个更高维的数组中.看到:

它可以作为array_agg_mult()下面自定义聚合函数的替代品.

Postgres 9.4或更高版本

任何数组类型的聚合函数

使用多态类型,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[]即使包含不同数量的维度).


Luk*_*und 2

使用内置的 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)