PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Записът, върнат от функцията, има конкатенирани колони

Като цяло,за разлагане на редове върнати от функция и да получите отделни колони:

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?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да емулирам вмъкване игнориране и при актуализиране на дублиран ключ (sql обединяване) с postgresql?

  2. Моите любими разширения на PostgreSQL - втора част

  3. Как да не създавате разширения PostgreSQL 9.0 на RPM платформи

  4. Операторът не съществува:цяло число =? когато използвате Postgres

  5. GROUP BY в Postgres - няма равенство за JSON тип данни?