Esto funciona:
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;
Llamar:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
O (actualización - ejemplo con cotización en dólares):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
-
Más información sobre cómo citar literales de cadena:
Insertar texto con comillas simples en PostgreSQL -
No necesita SQL dinámico aquí.
-
Mientras puedas envuélvalo en una función plpgsql (que puede ser útil), una función SQL simple está haciendo el trabajo bien.
-
Tiene desajustes de tipo .
- el resultado de
avg()
puede sernumeric
para mantener un resultado preciso. Lanzo afloat8
para que funcione, que es solo un alias paradouble precision
(puedes usar cualquiera). Si necesita una precisión perfecta, usenumeric
en su lugar. - Ya que
GROUP BY last_name
quieres untext
sin formato Parámetro OUT en lugar detext[]
.
- el resultado de
VARIADIC
Una matriz es un tipo útil de entrada. Si es más fácil para su cliente, también puede usar un VARIADIC
parámetro de entrada que permite pasar la matriz como una lista de elementos :
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;
Llamar:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
O (con cotización en dólares):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Tenga en cuenta que Postgres estándar solo permite un máximo de 100 elementos . Esto se determina en tiempo de compilación por la opción preestablecida:
max_function_args (integer)
Informa el número máximo de argumentos de función. Está determinado por el valor de FUNC_MAX_ARGS
al construir el servidor. El valor predeterminado es 100 argumentos.
Todavía puede llamarlo con notación de matriz cuando tiene el prefijo VARIADIC
:
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
Para arreglos más grandes (más de 100), también usaría unnest()
en una subconsulta y JOIN
a él, que tiende a escalar mejor:
- Optimización de una consulta de Postgres con un IN grande