PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Array iniziale in funzione per aggregare array multidimensionali

Postgres 9.5 o versioni successive

... viene fornito con una variante aggiuntiva della funzione di aggregazione array_agg() . Il manuale:

array di input concatenati in array di una dimensione superiore (gli input devono avere tutti la stessa dimensionalità e non possono essere vuoti o nulli)

Quindi non è esattamente la stessa della funzione di aggregazione personalizzata array_agg_mult() sotto. Ma usalo, se puoi. È più veloce.

Correlati:

  • Come ordinare un array int bidimensionale in PostgreSQL?

Postgres 9.4 o precedente

Funzione di aggregazione per qualsiasi tipo di matrice

Con il tipo polimorfico anyarray funziona con tutti i tipi di array (incluso integer[] ):

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

Come fornito da @Lukas, la funzione personalizzata arrayappend() non è necessario. Il built-in array_cat() fa il lavoro. Tuttavia, questo non spiega il perché il tuo esempio fallisce, mentre quello nella risposta di Lukas funziona. La differenza rilevante è che Lukas ha nidificato l'array in un altro livello di array con array[d.a] .

Inciampi nel presupposto errato che potresti dichiarare un tipo int[][] . Ma non puoi:int[][] è dello stesso tipo come int[] per il sistema di tipo PostgreSQL. Il capitolo sui tipi di array nel manuale spiega:

Anche l'attuale implementazione non applica il numero dichiarato di dimensioni. Le matrici di un particolare tipo di elemento sono tutte considerate dello stesso tipo, indipendentemente dalle dimensioni o dal numero di dimensioni. Quindi, dichiarando la dimensione dell'array o il numero di dimensioni inCREATE TABLE è semplicemente documentazione; non influisce sul comportamento in fase di esecuzione.

Un n -dimensional intero array è effettivamente un array di n-1 matrici -dimensionali di interi in PostgreSQL. Non puoi dirlo dal tipo che definisce solo l'elemento di base . Devi chiedere array_dims() per ottenere le specifiche.

Per dimostrare:

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

Oppure:

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

Tutti le colonne risultanti sono dello stesso tipo :int[] (anche se contiene un numero diverso di dimensioni).