Dette virker:
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;
Ring til:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
Eller (opdatering - eksempel med dollar-citering):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
-
Mere om, hvordan du citerer strenge bogstaver:
Indsæt tekst med enkelte anførselstegn i PostgreSQL -
Du behøver ikke dynamisk SQL her.
-
Mens du kan pak den ind i en plpgsql-funktion (som kan være nyttig), en simpel SQL-funktion klarer jobbet fint.
-
Du har typeuoverensstemmelser .
- resultatet af
avg()
kan værenumeric
at holde et præcist resultat. Jeg caster tilfloat8
for at få det til at fungere, hvilket blot er et alias fordouble precision
(du kan bruge begge dele). Hvis du har brug for perfekt præcision, skal du brugenumeric
i stedet. - Siden du
GROUP BY last_name
du vil have en almindeligtext
OUT parameter i stedet fortext[]
.
- resultatet af
VARIADIC
Et array er en nyttig type input. Hvis det er nemmere for din klient, kan du også bruge en VARIADIC
inputparameter, der gør det muligt at sende arrayet som en liste over elementer :
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;
Ring til:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
Eller (med dollar-angivelse):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Vær opmærksom på, at standard Postgres kun tillader maksimalt 100 elementer . Dette bestemmes på kompileringstidspunktet af den forudindstillede mulighed:
max_function_args (integer)
Rapporterer det maksimale antal funktionsargumenter. Det bestemmes af værdien af FUNC_MAX_ARGS
når du bygger serveren. Standardværdien er 100 argumenter.
Du kan stadig kalde det med array-notation, når det er præfikset med nøgleordet VARIADIC
:
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
For større arrays (100+), ville jeg også bruge unnest()
i en underforespørgsel og JOIN
til det, som har en tendens til at skalere bedre:
- Optimering af en Postgres-forespørgsel med et stort IN