sql >> Databáze >  >> RDS >> PostgreSQL

Připojte 2 sady na základě výchozího pořadí

Nyní, abychom odpověděli skutečné otázka, která byla odhalena v komentářích, která vypadá jako:

Existuje několik způsobů, jak to vyřešit:

  • Pokud a pouze v případě, že jsou pole stejně dlouhá, použijte více unnest funkce v SELECT klauzule (zastaralý přístup, který by se měl používat pouze pro zpětnou kompatibilitu);

  • Použijte generate_subscripts smyčka přes pole;

  • Použijte generate_series přes dílčí dotazy proti array_lower a array_upper emulovat generate_subscripts pokud potřebujete podporovat verze, které jsou příliš staré na to, aby měly generate_subscripts;

  • Spoléhání se na pořadí, které unnest vrací n-tice a doufá - jako v mé jiné odpovědi a jak je uvedeno níže. Bude to fungovat, ale není zaručeno, že to bude fungovat v budoucích verzích.

  • Použijte WITH ORDINALITY funkce přidané v PostgreSQL 9.4 (viz také jeho první příspěvek ), abyste získali číslo řádku pro unnest až vyjde 9.4.

  • Použijte UNNEST s více poli , což je standard SQL, ale který PostgreSQL zatím nepodporuje .

Řekněme tedy, že máme funkci arraypair s parametry pole a a 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;

a je vyvolán jako:

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

možné definice funkcí by byly:

SRF-in-SELECT (zastaralé)

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;

Pokud pole nebudou mít stejnou délku, vytvoří bizarní a neočekávané výsledky; podívejte se na dokumentaci o funkcích vracení sady a jejich nestandardním použití v SELECT seznam, abyste zjistili proč a co se přesně stalo.

generate_subscripts

Toto je pravděpodobně nejbezpečnější možnost:

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;

Pokud mají pole nestejnou délku, jak je napsáno, vrátí prvky null pro kratší, takže to funguje jako úplné vnější spojení. Obraťte smysl případu, abyste získali efekt podobný vnitřnímu spojení. Funkce předpokládá, že pole jsou jednorozměrná a že začínají na indexu 1. Pokud má celý argument pole hodnotu NULL, funkce vrátí hodnotu NULL.

Obecnější verze by byla napsána v PL/PgSQL a kontrolovala by array_ndims(a) = 1 , zkontrolujte array_lower(a, 1) = 1 , test na nulová pole atd. To nechám na vás.

Doufat v párové návraty:

Není zaručeno, že to bude fungovat, ale funguje to s aktuálním spouštěčem dotazů 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;

Zvažoval bych použití generate_subscripts mnohem bezpečnější.

Multi-argument unnest :

Toto by mělo funguje, ale ne, protože PostgreSQL unnest nepřijímá více vstupních polí (zatím):

SELECT * FROM unnest(a,b);


  1. Příklady RAND() v SQL Server

  2. FULLTEXT MySQL nebude fungovat s více než jedním polem

  3. MySQL versus SQL Server Express

  4. existuje alternativa k použití cyklu for pro vložení více dotazů