Over het algemeen om rijen te ontleden geretourneerd van een functie en krijgt individuele kolommen:
SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');
Wat betreft de vraag:
Postgres 9.3 of nieuwer
Opschonen met 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;
De LATERAL
trefwoord is hier impliciet, functies kunnen altijd eerder verwijzen FROM
artikelen. De handleiding:
LATERAL
kan ook voorafgaan aan een functieaanroepFROM
item, maar in dit geval is het een ruiswoord, omdat de functie-uitdrukking kan verwijzen naar eerderFROM
items in ieder geval.
Gerelateerd:
- Voeg meerdere rijen in een tabel in op basis van het aantal in een andere tabel
Korte notatie met een komma in de FROM
lijst is (meestal) gelijk aan een CROSS JOIN LATERAL
(hetzelfde als [INNER] JOIN LATERAL ... ON TRUE
) en verwijdert dus rijen uit het resultaat waar de functieaanroep geen rij retourneert. Om dergelijke rijen te behouden, gebruikt u LEFT JOIN LATERAL ... ON TRUE
:
...
FROM account_tab a
LEFT JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...
Gebruik ook niet NOT IN (subquery)
wanneer je het kunt vermijden. Het is de langzaamste en lastigste van de verschillende manieren om dat te doen:
- Selecteer rijen die niet aanwezig zijn in een andere tabel
Ik stel voor NOT EXISTS
in plaats daarvan.
Postgres 9.2 of ouder
U kunt een set-retourfunctie aanroepen in de SELECT
list (wat een Postgres-extensie is van standaard SQL). Om prestatieredenen kan dit het beste in een subquery worden gedaan. Ontbind het (bekende!) rijtype in de buitenste query om herhaalde evaluatie van de functie te voorkomen:
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;
Gerelateerd antwoord van Craig Ringer met een uitleg, waarom we beter kunnen ontleden in de buitenste vraag:
- Hoe vermijd je het evalueren van meerdere functies met de (func()).* syntaxis in een SQL-query?
Postgres 10 verwijderde eigenaardigheden in het gedrag van set-retourfuncties in de SELECT
:
- Wat is het verwachte gedrag voor functies die meerdere sets retourneren in de SELECT-component?