PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Array inicial em função para agregar array multidimensional

Postgres 9.5 ou mais recente


... vem com uma variante adicional da função agregada array_agg() . O manual:

arrays de entrada concatenados em array de uma dimensão superior (os inputs devem ter a mesma dimensionalidade e não podem ser vazios ou nulos)

Portanto, não é exatamente o mesmo que a função de agregação personalizada array_agg_mult() abaixo de. Mas use-o, se puder. É mais rápido.

Relacionado:
  • Como classificar array int bidimensional no PostgreSQL?

Postgres 9.4 ou anterior

Função agregada para qualquer tipo de matriz


Com o tipo polimórfico anyarray funciona para todos os tipos de arrays (incluindo integer[] ):
CREATE AGGREGATE array_agg_mult (anyarray) (
   SFUNC     = array_cat
 , STYPE     = anyarray
 , INITCOND  = '{}'
);

Conforme fornecido pelo @Lukas, a função personalizada arrayappend() Não é necessário. O array_cat() embutido faz o trabalho. No entanto, isso não explica por que seu exemplo falha, enquanto o da resposta de Lukas funciona. A diferença relevante é que Lukas aninhou o array em outra camada de array com array[d.a] .

Você tropeça na suposição incorreta de que poderia declarar um tipo int[][] . Mas você não pode:int[][] é do mesmo tipo como int[] para o sistema de tipos PostgreSQL. O capítulo sobre tipos de array no manual explica:

A implementação atual também não impõe o número declarado de dimensões. Arrays de um determinado tipo de elemento são todos considerados do mesmo tipo, independente do tamanho ou número de dimensões. Então, declarando o tamanho do array ou o número de dimensões em CREATE TABLE é simplesmente documentação; ele não afeta o comportamento em tempo de execução.

Um n array inteiro dimensional efetivamente é um array de n-1 arrays dimensionais de inteiros no PostgreSQL. Você não pode dizer isso a partir do tipo que define apenas o elemento base . Você tem que perguntar array_dims() para obter os detalhes.

Para demonstrar:
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);

Ou:
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 as colunas resultantes são do mesmo tipo :int[] (mesmo contendo um número diferente de dimensões).