sql >> Base de Datos >  >> RDS >> PostgreSQL

Matriz inicial en función de agregar una matriz multidimensional

Postgres 9.5 o posterior

... se envía con una variante adicional de la función agregada array_agg() . El manual:

matrices de entrada concatenadas en una matriz de una dimensión superior (todas las entradas deben tener la misma dimensionalidad y no pueden estar vacías o nulas)

Así que no es exactamente lo mismo que la función agregada personalizada array_agg_mult() abajo. Pero úsalo, si puedes. Es más rápido.

Relacionado:

  • ¿Cómo ordenar una matriz int bidimensional en PostgreSQL?

Postgres 9.4 o anterior

Función agregada para cualquiera tipo de matriz

Con el tipo polimórfico anyarray funciona para todo tipo de arreglos (incluyendo integer[] ):

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

Como proporcionó @Lukas, la función personalizada arrayappend() no es necesario. El array_cat() incorporado hace el trabajo. Sin embargo, eso no explica por qué su ejemplo falla, mientras que el de la respuesta de Lukas funciona. La diferencia relevante es que Lukas anidó la matriz en otra capa de matriz con array[d.a] .

Tropieza con la suposición incorrecta de que podría declarar un tipo int[][] . Pero no puedes:int[][] es del mismo tipo como int[] para el sistema de tipos PostgreSQL. El capítulo sobre tipos de matriz en el manual explica:

La implementación actual tampoco impone el número declarado de dimensiones. Los arreglos de un tipo de elemento en particular se consideran todos del mismo tipo, sin importar el tamaño o el número de dimensiones. Entonces, declarar el tamaño de la matriz o el número de dimensiones en CREATE TABLE es simplemente documentación; no afecta el comportamiento en tiempo de ejecución.

Un n matriz de enteros -dimensional efectivamente es una matriz de n-1 -matrices dimensionales de enteros en PostgreSQL. No se puede decir eso del tipo que solo define el elemento base . Tienes que preguntarle a array_dims() para obtener los detalles.

Para demostrar:

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);

O:

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);

Todos las columnas resultantes son del mismo tipo :int[] (aunque contenga un número diferente de dimensiones).