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

Разделете върнатия от функцията запис на множество колони

В Postgres 9.3 или по-късно това се решава най-добре с LATERAL присъединете се:

SELECT *
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Избягва многократно оценяване на функцията (за всяка колона в изхода - функцията трябва да бъде извикана за всеки входен ред така или иначе).
LEFT JOIN LATERAL ... ON true за да избегнете изпускането на редове от лявата страна, ако функцията не върне ред:

  • Каква е разликата между LATERAL и подзаявка в PostgreSQL?

Продължение във вашия коментар:

само разширените колони, произведени от извикването на функция

SELECT x.*  -- that's all!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LEFT   JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT  10;

Но тъй като не ви пука за други колони, можете да опростите до:

SELECT x.*
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
     , hi_lo(a.actor_id, length(a.name), ma.movie_id) x
LIMIT  10;

Което е имплицитно CROSS JOIN LATERAL . Ако функцията може действително да връща "no row" от време на време, резултатът може да бъде различен:ние не получаваме NULL стойности за редовете, тези редове просто се елиминират - и LIMIT не ги брои повече.

Впо-стари версии (или като цяло) можете също да разложите съставния тип с правилния синтаксис:

SELECT *, (hi_lo(a.actor_id, length(a.name), ma.movie_id)).*  -- note extra parentheses!
FROM   actors a 
JOIN   movies_actors ma on a.actor_id = ma.movie_id 
LIMIT  10;

Недостатъкът е, че функцията се оценява веднъж за всяка колона в изхода на функцията поради слабост в планера на заявки на Postgres. По-добре е да преместите повикването в подзаявка или CTE и да разложите типа на реда във външния SELECT . Като:

SELECT actor_id, movie_id, (x).*  -- explicit column names for the rest
FROM  (
   SELECT *, hi_lo(a.actor_id, length(a.name), ma.movie_id) AS x
   FROM   actors a 
   JOIN   movies_actors ma on a.actor_id = ma.movie_id 
   LIMIT  10
   ) sub;

Но трябва да наименувате отделни колони и не можете да се разминете с SELECT * освен ако не сте наред с вида на реда в резултата излишно. Свързано:

  • Избягвайте множество извиквания на една и съща функция, когато разширявате съставния резултат
  • Как да избегнем множество функции eval със синтаксиса (func()).* в SQL заявка?



  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 заявка за получаване на всички стойности, които едно изброяване може да има

  2. Как АКТУАЛИЗИРАТЕ и ИЗБЕРЕТЕ едновременно

  3. Топ GUI инструменти за PostgreSQL

  4. Автоматизирани надстройки на PostgreSQL клъстери в облак с почти нулев престой (част II)

  5. PostgreSQL - максимален брой параметри в IN клауза?