Généralement, pour décomposer les lignes renvoyé par une fonction et obtenir des colonnes individuelles :
SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');
Quant à la requête :
Postgres 9.3 ou version ultérieure
Nettoyeur avec 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;
Le LATERAL
le mot-clé est implicite ici, les fonctions peuvent toujours faire référence à FROM
antérieur éléments. Le manuel :
LATERAL
peut également précéder un appel de fonctionFROM
élément, mais dans ce cas, il s'agit d'un mot parasite, car l'expression de la fonction peut faire référence à unFROM
antérieur articles dans tous les cas.
Connexe :
- Insérer plusieurs lignes dans un tableau en fonction du nombre dans un autre tableau
Notation courte avec une virgule dans le FROM
list est (principalement) équivalent à un CROSS JOIN LATERAL
(identique à [INNER] JOIN LATERAL ... ON TRUE
) et supprime ainsi les lignes du résultat là où l'appel de fonction ne renvoie aucune ligne. Pour conserver ces lignes, utilisez LEFT JOIN LATERAL ... ON TRUE
:
...
FROM account_tab a
LEFT JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...
Aussi, n'utilisez pas NOT IN (subquery)
quand vous pouvez l'éviter. Il s'agit de la méthode la plus lente et la plus délicate :
- Sélectionnez les lignes qui ne sont pas présentes dans un autre tableau
Je suggère que NOT EXISTS
à la place.
Postgres 9.2 ou version antérieure
Vous pouvez appeler une fonction de retour d'ensemble dans le SELECT
list (qui est une extension Postgres du SQL standard). Pour des raisons de performances, il est préférable de le faire dans une sous-requête. Décomposez le type de ligne (bien connu !) dans la requête externe pour éviter une évaluation répétée de la fonction :
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;
Réponse connexe de Craig Ringer avec une explication, pourquoi nous ferions mieux de décomposer dans la requête externe :
- Comment éviter plusieurs évaluations de fonction avec la syntaxe (func()).* dans une requête SQL ?
Postgres 10 suppression des bizarreries dans le comportement des fonctions de retour d'ensemble dans le SELECT
:
- Quel est le comportement attendu pour plusieurs fonctions renvoyant des ensembles dans la clause SELECT ?