Dit werkt:
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;
Bel:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
Of (update - voorbeeld met dollaraanhalingstekens):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
-
Meer over het citeren van letterlijke tekenreeksen:
Voeg tekst in met enkele aanhalingstekens in PostgreSQL -
Je hebt hier geen dynamische SQL nodig.
-
Terwijl je kunt wikkel het in een plpgsql-functie (wat handig kan zijn), een eenvoudige SQL-functie doet het werk prima.
-
U heeft niet-overeenkomende typen .
- het resultaat van
avg()
kannumeric
zijn om een nauwkeurig resultaat vast te houden. Ik cast naarfloat8
om het te laten werken, wat slechts een alias is voordouble precision
(je kunt beide gebruiken). Als je perfecte precisie nodig hebt, gebruik dannumeric
in plaats daarvan. - Sinds je
GROUP BY last_name
je wilt een plattetext
OUT-parameter in plaats vantext[]
.
- het resultaat van
VARIADIC
Een array is een handig type invoer. Als het voor uw klant gemakkelijker is, kunt u ook een VARIADIC
. gebruiken invoerparameter waarmee de array kan worden doorgegeven als een lijst met elementen :
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;
Oproep:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
Of (met dollaraanhaling):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Houd er rekening mee dat standaard Postgres slechts een maximaal 100 elementen toestaat . Dit wordt tijdens het compileren bepaald door de vooraf ingestelde optie:
max_function_args (integer)
Rapporteert het maximum aantal functieargumenten. Het wordt bepaald door de waarde van
FUNC_MAX_ARGS
bij het bouwen van de server. De standaardwaarde is 100 argumenten.
Je kunt het nog steeds aanroepen met array-notatie als het wordt voorafgegaan door het trefwoord VARIADIC
:
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
Voor grotere arrays (100+), zou ik ook unnest()
. gebruiken in een subquery en JOIN
ernaartoe, wat beter schaalt:
- Een Postgres-query optimaliseren met een grote IN