PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Restituisce le righe corrispondenti agli elementi dell'array di input nella funzione plpgsql

Funziona:

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;

Chiama:

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

Oppure (aggiornamento - esempio con virgolette in dollari):

SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
  • Ulteriori informazioni su come citare le stringhe letterali:
    Inserisci testo con virgolette singole in PostgreSQL

  • Non hai bisogno di SQL dinamico qui.

  • Mentre tu puoi avvolgerlo in una funzione plpgsql (che potrebbe essere utile), una semplice funzione SQL sta facendo il lavoro bene.

  • Hai tipo non corrispondente .

    • il risultato di avg() può essere numeric per mantenere un risultato preciso. Ho lanciato su float8 per farlo funzionare, che è solo un alias per double precision (puoi usare entrambi). Se hai bisogno di una precisione perfetta, usa numeric invece.
    • Dato che GROUP BY last_name vuoi un semplice text Parametro OUT invece di text[] .

VARIADIC

Un array è un utile tipo di input. Se è più facile per il tuo cliente puoi anche usare un VARIADIC parametro di input che permette di passare l'array come elenco di elementi :

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;

Chiama:

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

Oppure (con quotazione in dollari):

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

Tieni presente che Postgres standard consente solo un massimo di 100 elementi . Ciò è determinato in fase di compilazione dall'opzione preimpostata:

max_function_args (integer)

Riporta il numero massimo di argomenti della funzione. È determinato dal valore di FUNC_MAX_ARGS durante la creazione del server. Il valore predefinito è 100 argomenti.

Puoi ancora chiamarlo con la notazione array quando è preceduto dalla parola chiave VARIADIC :

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

Per array più grandi (100+), userei anche unnest() in una sottoquery e JOIN ad esso, che tende a scalare meglio:

  • Ottimizzazione di una query Postgres con un IN grande