sql >> Databasteknik >  >> RDS >> PostgreSQL

Returnera rader som matchar element i inmatningsmatrisen i plpgsql-funktionen

Detta fungerar:

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:

SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');

Eller (uppdatering - exempel med dollarnotering):

SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
  • Mer om hur man citerar bokstavliga strängar:
    Infoga text med enstaka citattecken i PostgreSQL

  • Du behöver inte dynamisk SQL här.

  • Medan du kan linda in det i en plpgsql-funktion (vilket kan vara användbart), en enkel SQL-funktion gör jobbet bra.

  • Du har felmatchningar .

    • resultatet av avg() kan vara numeric för att hålla ett exakt resultat. Jag castar till float8 för att få det att fungera, vilket bara är ett alias för double precision (du kan använda antingen). Om du behöver perfekt precision, använd numeric istället.
    • Eftersom du GROUP BY last_name du vill ha en vanlig text OUT-parameter istället för text[] .

VARIADIC

En array är en användbar typ av indata. Om det är lättare för din klient kan du också använda en VARIADIC indataparameter som gör det möjligt att skicka arrayen som en lista med element :

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:

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');

Eller (med dollarnotering):

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);

Var medveten om att standard Postgres endast tillåter max 100 element . Detta bestäms vid kompilering av det förinställda alternativet:

max_function_args (integer)

Rapporterar det maximala antalet funktionsargument. Det bestäms av värdet på FUNC_MAX_ARGS när du bygger servern. Standardvärdet är 100 argument.

Du kan fortfarande kalla det med arraynotation när det är prefixet med nyckelordet VARIADIC :

SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');

För större arrayer (100+) skulle jag också använda unnest() i en underfråga och JOIN till det, som tenderar att skala bättre:

  • Optimera en Postgres-fråga med ett stort IN



  1. Hur man analyserar aktiviteten i en databas i SQL Server

  2. 5 skäl till varför du behöver en bra databas

  3. Hur använder jag det aktuella datumet i en HQL-fråga med en Oracle-databas?

  4. Felsökning av problem när du arbetar med datum och tid i SQL Server