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ò esserenumeric
per mantenere un risultato preciso. Ho lanciato sufloat8
per farlo funzionare, che è solo un alias perdouble precision
(puoi usare entrambi). Se hai bisogno di una precisione perfetta, usanumeric
invece. - Dato che
GROUP BY last_name
vuoi un semplicetext
Parametro OUT invece ditext[]
.
- il risultato di
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