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

Unisci 2 set in base all'ordine predefinito

Ora, per rispondere al reale domanda che è stata rivelata nei commenti, che sembra essere qualcosa del tipo:

Ci sono un paio di modi per affrontare questo problema:

  • Se e solo se gli array hanno la stessa lunghezza, usa più unnest funzioni nel SELECT clausola (un approccio deprecato che dovrebbe essere utilizzato solo per la compatibilità con le versioni precedenti);

  • Usa generate_subscripts per scorrere gli array;

  • Usa generate_series su sottoquery su array_lower e array_upper per emulare generate_subscripts se devi supportare versioni troppo vecchie per avere generate_subscripts;

  • Basandosi sull'ordine che unnest restituisce tuple e sperando, come nell'altra mia risposta e come mostrato di seguito. Funzionerà, ma non è garantito che funzioni nelle versioni future.

  • Usa il WITH ORDINALITY funzionalità aggiunta in PostgreSQL 9.4 (vedi anche il suo primo invio ) per ottenere un numero di riga per unnest quando esce 9.4.

  • Usa più array UNNEST , che è standard SQL ma che PostgreSQL non supporta ancora .

Quindi, supponiamo di avere la funzione arraypair con i parametri dell'array a e b :

CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[]) 
RETURNS TABLE (col_a integer, col_b text) AS $$
  -- blah code here blah
$$ LANGUAGE whatever IMMUTABLE;

ed è invocato come:

SELECT * FROM arraypair( ARRAY[1,2,3,4,5,6,7], ARRAY['a','b','c','d','e','f','g'] );

possibili definizioni di funzione sarebbero:

SRF-in-SELECT (obsoleto)

CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
    SELECT unnest(a), unnest(b);
$$ LANGUAGE sql IMMUTABLE;

Produrrà risultati bizzarri e inaspettati se gli array non hanno la stessa lunghezza; vedere la documentazione sulle funzioni di ritorno degli insiemi e sul loro uso non standard in SELECT elenco per sapere perché e cosa succede esattamente.

generate_subscripts

Questa è probabilmente l'opzione più sicura:

CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
    SELECT
       a[i], b[i]
    FROM generate_subscripts(CASE WHEN array_length(a,1) >= array_length(b,1) THEN a::text[] ELSE b::text[] END, 1) i;
$$ LANGUAGE sql IMMUTABLE;

Se gli array sono di lunghezza diversa, come scritto restituirà elementi null per il più breve, quindi funziona come un join esterno completo. Invertire il senso del caso per ottenere un effetto simile all'unione interna. La funzione presuppone che gli array siano unidimensionali e che inizino dall'indice 1. Se l'intero argomento dell'array è NULL, la funzione restituisce NULL.

Una versione più generalizzata verrebbe scritta in PL/PgSQL e verificherebbe array_ndims(a) = 1 , controlla array_lower(a, 1) = 1 , prova per array nulli, ecc. Lo lascio a te.

Sperando in ritorni a coppie:

Non è garantito che funzioni, ma funziona con l'attuale esecutore di query di PostgreSQL:

CREATE OR REPLACE FUNCTION arraypair (a integer[], b text[])
RETURNS TABLE (col_a integer, col_b text) AS $$
 WITH
    rn_c1(rn, col) AS (
      SELECT row_number() OVER (), c1.col
      FROM unnest(a) c1(col) 
    ),
    rn_c2(rn, col) AS (
      SELECT row_number() OVER (), c2.col
      FROM unnest(b) c2(col)
    )
    SELECT
      rn_c1.col AS c1, 
      rn_c2.col AS c2
    FROM rn_c1 
    INNER JOIN rn_c2 ON (rn_c1.rn = rn_c2.rn);
$$ LANGUAGE sql IMMUTABLE;

Prenderei in considerazione l'utilizzo di generate_subscripts molto più sicuro.

Multi-argomento unnest :

Questo dovrebbe funziona, ma non perché unnest di PostgreSQL non accetta più array di input (ancora):

SELECT * FROM unnest(a,b);