sql >> Base de Datos >  >> RDS >> PostgreSQL

Devolver filas que coincidan con los elementos de la matriz de entrada en la función plpgsql

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 ser numeric para mantener un resultado preciso. Lanzo a float8 para que funcione, que es solo un alias para double precision (puedes usar cualquiera). Si necesita una precisión perfecta, use numeric en su lugar.
    • Ya que GROUP BY last_name quieres un text sin formato Parámetro OUT en lugar de text[] .

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