PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Rekord zwrócony z funkcji zawiera połączone kolumny

Ogólnie aby rozłożyć wiersze zwrócone z funkcji i uzyskać poszczególne kolumny:

SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');

Co do zapytania:

Postgres 9.3 lub nowszy

Czyszczenie z 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 słowo kluczowe jest tutaj niejawne, funkcje zawsze mogą odwoływać się do wcześniejszego FROM rzeczy. Instrukcja:

LATERAL może również poprzedzać wywołanie funkcji FROM item, ale w tym przypadku jest to słowo zakłócające, ponieważ wyrażenie funkcji może odnosić się do wcześniejszego FROM przedmioty w każdym przypadku.

Powiązane:

  • Wstaw wiele wierszy w jednej tabeli na podstawie numeru w innej tabeli

Krótka notacja z przecinkiem w FROM lista jest (w większości) odpowiednikiem CROSS JOIN LATERAL (tak samo jak [INNER] JOIN LATERAL ... ON TRUE ), a tym samym usuwa wiersze z wyniku, w których wywołanie funkcji nie zwraca żadnego wiersza. Aby zachować takie wiersze, użyj LEFT JOIN LATERAL ... ON TRUE :

...
FROM  account_tab a
LEFT  JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
...

Nie używaj także NOT IN (subquery) kiedy możesz tego uniknąć. Jest to najwolniejszy i najtrudniejszy z kilku sposobów, aby to zrobić:

  • Wybierz wiersze, których nie ma w innej tabeli

Proponuję NOT EXISTS zamiast tego.

Postgres 9.2 lub starszy

Możesz wywołać funkcję zwracającą zestaw w SELECT list (która jest rozszerzeniem Postgresa standardowego SQL). Ze względu na wydajność najlepiej jest to zrobić w podzapytaniu. Zdekomponuj (dobrze znany!) typ wiersza w zewnętrznym zapytaniu, aby uniknąć powtórnej oceny funkcji:

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;

Powiązana odpowiedź Craiga Ringera z wyjaśnieniem, dlaczego lepiej rozkładać się w zewnętrznym zapytaniu:

  • Jak uniknąć wielu ewaluacji funkcji za pomocą składni (func()).* w zapytaniu SQL?

Postgres 10 usunięto osobliwości w zachowaniu funkcji zwracających zestaw w SELECT :

  • Jakie jest oczekiwane zachowanie wielu funkcji zwracających zestaw w klauzuli 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. Wydajność aplikacji opartych na PostgreSQL:opóźnienia i ukryte opóźnienia

  2. Wywołanie procedury składowanej w ramach procedury składowanej

  3. Wybrać pierwszy wiersz w każdej grupie GROUP BY?

  4. Wykonywanie sekwencji i seriali w Postgres-XL

  5. Zwróć wiersze pasujące do elementów tablicy wejściowej w funkcji plpgsql