sql >> Databasteknik >  >> RDS >> PostgreSQL

Gå med i 2 set baserat på standardordning

För att nu svara på det riktiga fråga som avslöjades i kommentarer, som verkar vara något i stil med:

Det finns ett par sätt att tackla detta:

  • Om och bara om arrayerna är lika långa, använd flera unnest funktioner i SELECT klausul (en föråldrad metod som endast bör användas för bakåtkompatibilitet);

  • Använd generate_subscripts att loopa över arrayerna;

  • Använd generate_series över delfrågor mot array_lower och array_upper för att emulera generate_subscripts om du behöver stödja versioner som är för gamla för att ha generate_subscripts;

  • Förlitar sig på ordern som unnest returnerar tuples in och hoppas - som i mitt andra svar och som visas nedan. Det kommer att fungera, men det är inte garanterat att det fungerar i framtida versioner.

  • Använd den WITH ORDINALITY funktionalitet tillagd i PostgreSQL 9.4 (se även dess första inlägg ) för att få ett radnummer för unnest när 9.4 kommer ut.

  • Använd UNNEST med flera arrayer , som är SQL-standard men vilket PostgreSQL stöder inte ännu .

Så säg att vi har funktionen arraypair med arrayparametrar a och 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;

och det anropas som:

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

möjliga funktionsdefinitioner skulle vara:

SRF-in-SELECT (utfasad)

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;

Kommer att ge bisarra och oväntade resultat om arrayerna inte är lika långa; se dokumentationen om uppsättningsreturfunktioner och deras icke-standardiserade användning i SELECT lista för att lära dig varför och vad som händer exakt.

generate_subscripts

Detta är förmodligen det säkraste alternativet:

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;

Om arrayerna är av olika längd, som skrivet, kommer det att returnera nollelement för det kortare, så det fungerar som en fullständig yttre koppling. Vänd om känslan av fallet för att få en inre sammanfogningsliknande effekt. Funktionen antar att arrayerna är endimensionella och att de börjar vid index 1. Om ett helt arrayargument är NULL returnerar funktionen NULL.

En mer generaliserad version skulle skrivas i PL/PgSQL och skulle kontrollera array_ndims(a) = 1 , kontrollera array_lower(a, 1) = 1 , testa för nollmatriser, etc. Jag överlåter det till dig.

Hoppas på parvis avkastning:

Det här fungerar inte garanterat, men det gör det med PostgreSQL:s nuvarande frågeexekutor:

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;

Jag skulle överväga att använda generate_subscripts mycket säkrare.

Multi-argument unnest :

Detta bör fungerar, men gör det inte eftersom PostgreSQL:s unnest accepterar inte flera inmatningsmatriser (ännu):

SELECT * FROM unnest(a,b);


  1. läser BLOB-bild från MySQL-databas

  2. Hur man ansluter till MySQL som körs på Docker från värddatorn

  3. FEL:arraystorleken överskrider det maximalt tillåtna (1073741823)

  4. Fördelarna med PostgreSQL