Като цяло,за разлагане на редове върнати от функция и да получите отделни колони:
SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');
Що се отнася до заявката:
Postgres 9.3 или по-нова версия
Почистващо средство с 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
ключовата дума тук е имплицитна, функциите винаги могат да препращат по-рано FROM
артикули. Ръководството:
LATERAL
може също да предшества извикване на функцияFROM
елемент, но в този случай това е шумна дума, тъй като изразът на функцията може да се отнася до по-раннияFROM
елементи във всеки случай.
Свързано:
- Вмъкнете няколко реда в една таблица въз основа на число в друга таблица
Кратка нотация със запетая в FROM
списъкът е (предимно) еквивалентен на CROSS JOIN LATERAL
(същото като [INNER] JOIN LATERAL ... ON TRUE
) и по този начин премахва редове от резултата, където извикването на функцията не връща ред. За да запазите такива редове, използвайте LEFT JOIN LATERAL ... ON TRUE
:
...
FROM account_tab a
LEFT JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...
Също така, не използвайте NOT IN (subquery)
когато можете да го избегнете. Това е най-бавният и труден от няколко начина за това:
- Изберете редове, които не присъстват в друга таблица
Предлагам NOT EXISTS
вместо това.
Postgres 9.2 или по-стара версия
Можете да извикате функция за връщане на набор в SELECT
списък (който е разширение на Postgres на стандартния SQL). От съображения за производителност това е най-добре да се направи в подзаявка. Разложете (добре познат!) тип ред във външната заявка, за да избегнете повторна оценка на функцията:
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;
Свързан отговор от Крейг Рингър с обяснение защо е по-добре да декомпозираме във външната заявка:
- Как да избегнем множество функции eval със синтаксиса (func()).* в SQL заявка?
Postgres 10 премахнати странностите в поведението на функциите за връщане на набори в SELECT
:
- Какво е очакваното поведение за множество функции, връщащи набор в клауза SELECT?