【问题标题】:Initial array in function to aggregate multi-dimensional array聚合多维数组的函数中的初始数组
【发布时间】:2012-04-07 15:29:30
【问题描述】:

我有一个包含整数数组的表。

我想创建一个聚合函数,它将返回一个包含所有行的二维数组。然后将其传递给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[][]

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

【问题讨论】:

    标签: arrays postgresql multidimensional-array aggregate-functions


    【解决方案1】:

    使用内置的array_cat 函数有效。

    CREATE AGGREGATE array_sum2 (int[])  (
        SFUNC     = array_cat,
        STYPE     = int[],
        INITCOND  = '{}'
    );
    

    测试:

    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}}
    

    【讨论】:

      【解决方案2】:

      Postgres 9.5 或更新版本

      ... 附带聚合函数 array_agg() 的附加变体。 The manual:

      输入数组连接成一维数组(输入 必须都具有相同的维度,并且不能为空或 null)

      所以和下面的自定义聚合函数array_agg_mult()不完全一样。但是,如果可以的话,请使用它。它更快。

      相关:

      Postgres 9.4 或更早版本

      any 数组类型的聚合函数

      使用polymorphic type anyarray,它适用于各种数组(包括integer[]):

      CREATE AGGREGATE array_agg_mult (anyarray) (
         SFUNC     = array_cat
       , STYPE     = anyarray
       , INITCOND  = '{}'
      );
      

      正如@Lukas 提供的那样,不需要自定义函数arrayappend()。内置的array_cat() 可以完成这项工作。但是,这并不能解释 为什么 您的示例失败,而 Lukas 的答案中的示例却有效。相关的区别是 Lukas 将数组嵌套到另一个数组层中,array[d.a]

      您误认为可以声明类型int[][]。但你不能:int[][] 与 PostgreSQL 类型系统的int[]相同类型chapter on array types in the manual 解释说:

      当前的实现不强制声明的数量 尺寸。特定元素类型的数组都是 被认为是同一类型,无论大小或数量 方面。因此,在中声明数组大小或维数 CREATE TABLE 只是文档;它不会影响运行时行为。

      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[](即使包含不同数量的维度)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-23
        • 2015-08-01
        • 1970-01-01
        • 2016-12-06
        • 1970-01-01
        相关资源
        最近更新 更多