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

Rozdělte záznam vrácený funkcí do více sloupců

V Postgres 9.3 nebo později to lze nejlépe vyřešit pomocí LATERAL připojit se:

SELECT *
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Zabraňuje opakovanému vyhodnocování funkce (pro každý sloupec na výstupu – funkce musí být volána pro každý vstupní řádek v obou směrech).
LEFT JOIN LATERAL ... ON true abyste předešli vypuštění řádků z levé strany, pokud funkce nevrátí žádný řádek:

  • Jaký je rozdíl mezi LATERAL a dílčím dotazem v PostgreSQL?

Následná reakce ve vašem komentáři:

pouze rozbalené sloupce vytvořené voláním funkce

SELECT x.*  -- that's all!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Ale protože vás nezajímají další sloupce, můžete to zjednodušit na:

SELECT x.*
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
     , hi_lo(a.actor_id, length(a.name), ma.movie_id) x
LIMIT  10;

Což je implicitní CROSS JOIN LATERAL . Pokud může funkce skutečně příležitostně vrátit „žádný řádek“, výsledek může být jiný:pro řádky nezískáme hodnoty NULL, tyto řádky jsou pouze odstraněny – a LIMIT už je nepočítá.

Ve starších verzích (nebo obecně) můžete také jednoduše rozložit složený typ se správnou syntaxí:

SELECT *, (hi_lo(a.actor_id, length(a.name), ma.movie_id)).*  -- note extra parentheses!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LIMIT  10;

Nevýhodou je, že funkce je vyhodnocena jednou pro každý sloupec ve výstupu funkce kvůli slabosti plánovače dotazů Postgres. Je lepší přesunout volání do poddotazu nebo CTE a rozložit typ řádku ve vnějším SELECT . Jako:

SELECT actor_id, movie_id, (x).*  -- explicit column names for the rest
FROM  (
   SELECT *, hi_lo(a.actor_id, length(a.name), ma.movie_id) AS x
   FROM   actors a 
   JOIN   movies_actors ma on a.actor_id = ma.movie_id 
   LIMIT  10
   ) sub;

Ale musíte pojmenovat jednotlivé sloupce a nemůžete se zbavit SELECT * pokud nejste v pořádku s typem řádku ve výsledku redundantně. Související:

  • Při rozbalování složeného výsledku se vyhněte vícenásobnému volání stejné funkce
  • Jak se vyhnout vícenásobným hodnotám funkcí pomocí syntaxe (func()).* v dotazu SQL?



  1. Ukládání šifrovaných dat v Postgresu

  2. Chybová zpráva sqldeveloper:Síťový adaptér nemohl navázat chybu připojení

  3. Způsoby, jak vědět, jak se vypořádat s korupcí databáze na serveru SQL

  4. Proč se doba provádění uložené procedury Oracle výrazně prodlužuje v závislosti na způsobu jejího provádění?