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

Deltag i 2 sæt baseret på standardrækkefølge

For nu at besvare det rigtige spørgsmål, der blev afsløret i kommentarer, som ser ud til at være noget i stil med:

Der er et par måder at tackle dette på:

  • Hvis og kun hvis arrays er lige lange, skal du bruge flere unnest funktioner i SELECT klausul (en forældet tilgang, der kun bør bruges til bagudkompatibilitet);

  • Brug generate_subscripts at sløjfe over arrays;

  • Brug generate_series over underforespørgsler mod array_lower og array_upper at emulere generate_subscripts hvis du skal understøtte versioner, der er for gamle til at have generate_subscripts;

  • Stoler på rækkefølgen, der unnest returnerer tuples i og håbe - ligesom i mit andet svar og som vist nedenfor. Det vil virke, men det er ikke garanteret, at det virker i fremtidige versioner.

  • Brug WITH ORDINALITY funktionalitet tilføjet i PostgreSQL 9.4 (se også dens første opslag ) for at få et rækkenummer for unnest når 9.4 kommer ud.

  • Brug multiple-array UNNEST , som er SQL-standard, men hvilket PostgreSQL understøtter ikke endnu .

Så lad os sige, at vi har funktionen arraypair med array-parametre a og 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;

og det kaldes som:

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

mulige funktionsdefinitioner ville være:

SRF-in-SELECT (forældet)

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;

Vil producere bizarre og uventede resultater, hvis arrays ikke er lige lange; se dokumentationen om sæt returnerende funktioner og deres ikke-standard brug i SELECT liste for at lære hvorfor, og hvad der præcist sker.

generate_subscripts

Dette er sandsynligvis den sikreste mulighed:

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;

Hvis arrays er af forskellig længde, vil det som skrevet returnere nul-elementer for de kortere, så det fungerer som en fuld ydre joinforbindelse. Vend sagens forstand for at få en indre-sammenføjningslignende effekt. Funktionen antager, at arrays er endimensionelle, og at de starter ved indeks 1. Hvis et helt array-argument er NULL, returnerer funktionen NULL.

En mere generaliseret version ville blive skrevet i PL/PgSQL og ville kontrollere array_ndims(a) = 1 , tjek array_lower(a, 1) = 1 , test for nul-arrays osv. Jeg overlader det til dig.

Håber på parvise afkast:

Dette er ikke garanteret at virke, men gør det med PostgreSQL's nuværende forespørgselseksekutor:

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;

Jeg ville overveje at bruge generate_subscripts meget sikrere.

Multi-argument unnest :

Dette skal virker, men gør det ikke fordi PostgreSQL's unnest accepterer ikke flere input-arrays (endnu):

SELECT * FROM unnest(a,b);


  1. diff 2 store databasetabeller

  2. Sådan opretter du en serverløs GraphQL API til MySQL, Postgres og Aurora

  3. Opdatering af en deltagelsesvisning uden at få en fejlmeddelelse om ikke-nøglebevaret

  4. Fejl:PLS-00428:Der forventes en into-klausul i denne select-sætning