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

Record returneret fra funktion har kolonner sammenkædet

Generelt for at dekomponere rækker returneres fra en funktion og få individuelle kolonner:

SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');

Med hensyn til forespørgslen:

Postgres 9.3 eller nyere

Renser med JOIN LATERAL :

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , f.*   -- but avoid duplicate column names!
FROM   account_tab a
     , account_servicetier_for_day(a.accountid, '2014-08-12') f  -- <-- HERE
WHERE  a.isdsl = 1
AND    a.dslservicetypeid IS NOT NULL
AND    NOT EXISTS (
   SELECT 1
   FROM   dailyaccounting_tab
   WHERE  day = '2014-08-12'
   AND    accountid = a.accountid
   )
ORDER  BY a.username;

LATERAL nøgleordet er implicit her, funktioner kan altid henvise til tidligere FROM genstande. Manualen:

LATERAL kan også gå forud for et funktionskald FROM element, men i dette tilfælde er det et støjord, fordi funktionsudtrykket kan henvise til tidligere FROM varer under alle omstændigheder.

Relateret:

  • Indsæt flere rækker i én tabel baseret på antallet i en anden tabel

Kort notation med komma i FROM liste svarer (for det meste) til en CROSS JOIN LATERAL (samme som [INNER] JOIN LATERAL ... ON TRUE ) og fjerner dermed rækker fra resultatet, hvor funktionskaldet ikke returnerer nogen række. For at beholde sådanne rækker skal du bruge LEFT JOIN LATERAL ... ON TRUE :

...
FROM  account_tab a
LEFT  JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...

Brug heller ikke NOT IN (subquery) når du kan undgå det. Det er den langsomste og mest vanskelige af flere måder at gøre det på:

  • Vælg rækker, der ikke findes i en anden tabel

Jeg foreslår at NOT EXISTS i stedet.

Postgres 9.2 eller ældre

Du kan kalde en sæt-retur-funktion i SELECT liste (som er en Postgres-udvidelse af standard SQL). Af ydeevnemæssige årsager gøres dette bedst i en underforespørgsel. Dekomponér den (velkendte!) rækketype i den ydre forespørgsel for at undgå gentagen evaluering af funktionen:

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , (a.rec).*   -- but avoid duplicate column names!
FROM  (
   SELECT *, account_servicetier_for_day(a.accountid, '2014-08-12') AS rec
   FROM   account_tab a
   WHERE  a.isdsl = 1
   AND    a.dslservicetypeid Is Not Null
   AND    NOT EXISTS (
       SELECT 1
       FROM   dailyaccounting_tab
       WHERE  day = '2014-08-12'
       AND    accountid = a.accountid
      )
   ) a
ORDER  BY a.username;

Relateret svar af Craig Ringer med en forklaring, hvorfor vi bedre kan dekomponere i den ydre forespørgsel:

  • Hvordan undgår man flere funktionsevaler med (func()).*-syntaksen i en SQL-forespørgsel?

Postgres 10 fjernede mærkværdigheder i adfærden for sæt-returnerende funktioner i SELECT :

  • Hvad er den forventede adfærd for flere sæt-returnerende funktioner i SELECT-sætning?


  1. Vælg gruppe af rækker, der matcher alle elementer på en liste

  2. Konverter en juliansk dag til en dato i PostgreSQL

  3. Skal jeg oprette indekser på fremmednøgler på Oracle?

  4. SQLite SUBSTRING() Forklaret