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

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

To działa:

CREATE OR REPLACE FUNCTION avg_purchases(last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   WHERE  last_name = ANY($1)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Zadzwoń:

SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');

Lub (aktualizacja - przykład z cytatem w dolarach):

SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
  • Więcej informacji o cytowaniu literałów ciągu:
    Wstaw tekst z pojedynczymi cudzysłowami w PostgreSQL

  • Nie potrzebujesz tutaj dynamicznego SQL.

  • Chociaż możesz zapakuj go w funkcję plpgsql (co może być przydatne), prosta funkcja SQL wykonuje to zadanie dobrze.

  • Masz niezgodności typów .

    • wynik avg() może być numeric aby uzyskać dokładny wynik. Przesyłam do float8 aby to działało, co jest tylko aliasem dla double precision (możesz użyć albo). Jeśli potrzebujesz doskonałej precyzji, użyj numeric zamiast tego.
    • Ponieważ GROUP BY last_name chcesz zwykły text Parametr OUT zamiast text[] .

VARIADIC

Tablica jest użytecznym typem danych wejściowych. Jeśli jest to łatwiejsze dla Twojego klienta, możesz również użyć VARIADIC parametr wejściowy pozwalający na przekazanie tablicy jako listy elementów :

CREATE OR REPLACE FUNCTION avg_purchases(VARIADIC last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   JOIN  (SELECT unnest($1)) t(last_name) USING (last_name)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Zadzwoń:

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');

Lub (z cytatem w dolarach):

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);

Pamiętaj, że standardowy Postgres zezwala na maksymalnie 100 elementów . Jest to określane w czasie kompilacji przez opcję ustawień wstępnych:

max_function_args (integer)

Podaje maksymalną liczbę argumentów funkcji. Określa ją wartość FUNC_MAX_ARGS podczas budowania serwera. Domyślna wartość to 100 argumentów.

Nadal można go wywoływać za pomocą notacji tablicowej, jeśli jest poprzedzony słowem kluczowym VARIADIC :

SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');

W przypadku większych tablic (100+) użyłbym również unnest() w podzapytaniu i JOIN do niego, co ma tendencję do lepszego skalowania:

  • Optymalizacja zapytania Postgres z dużym IN



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. błąd instrukcji sql:kolumna .. nie istnieje

  2. PostgreSQL CASE ... END z wieloma warunkami

  3. Programowo wyprodukuj obiekt `DataSource` dla Postgres JDBC

  4. Postgres Query Plan, dlaczego szacowanie wierszy jest tak błędne

  5. Przechowywanie długich ciągów binarnych (surowych danych)