PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Tableau initial en fonction pour agréger un tableau multidimensionnel

Postgres 9.5 ou version ultérieure

... est livré avec une variante supplémentaire de la fonction d'agrégation array_agg() . Le manuel :

tableaux d'entrée concaténés dans un tableau d'une dimension supérieure (les entrées doivent toutes avoir la même dimensionnalité et ne peuvent pas être vides ou nulles)

Donc pas exactement la même chose que la fonction d'agrégation personnalisée array_agg_mult() au dessous de. Mais utilisez-le, si vous le pouvez. C'est plus rapide.

Connexe :

  • Comment trier un tableau int à deux dimensions dans PostgreSQL ?

Postgres 9.4 ou version antérieure

Fonction d'agrégation pour tous type de tableau

Avec le type polymorphe anyarray cela fonctionne pour toutes sortes de tableaux (y compris integer[] ):

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

Comme @Lukas l'a fourni, la fonction personnalisée arrayappend() n'est pas nécessaire. Le array_cat() intégré Fait le travail. Cependant, cela n'explique pas pourquoi votre exemple échoue, tandis que celui de la réponse de Lukas fonctionne. La différence pertinente est que Lukas a imbriqué le tableau dans une autre couche de tableau avec array[d.a] .

Vous trébuchez sur l'hypothèse incorrecte selon laquelle vous pourriez déclarer un type int[][] . Mais vous ne pouvez pas :int[][] est du même type comme int[] pour le système de type PostgreSQL. Le chapitre sur les types de tableaux dans le manuel explique :

L'implémentation actuelle n'applique pas non plus le nombre de dimensions déclaré. Les tableaux d'un type d'élément particulier sont tous considérés comme étant du même type, indépendamment de la taille ou du nombre de dimensions. Ainsi, déclarer la taille du tableau ou le nombre de dimensions dans CREATE TABLE est simplement de la documentation ; cela n'affecte pas le comportement d'exécution.

Un n Le tableau d'entiers dimensionnel est effectivement un tableau de n-1 -tableaux dimensionnels d'entiers dans PostgreSQL. Vous ne pouvez pas le dire à partir du type qui définit uniquement l'élément de base . Vous devez demander array_dims() pour obtenir les détails.

Pour démontrer :

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

Tous les colonnes résultantes sont du même type :int[] (même s'il contient un nombre différent de dimensions).