Bri*_*n B 3 arrays postgresql plpgsql aggregate-functions postgresql-9.2
我想创建一个PostgreSQL函数,它执行以下操作:
CREATE FUNCTION avg_purchases( IN last_names text[] DEFAULT '{}' )
RETURNS TABLE(last_name text[], avg_purchase_size double precision)
AS
$BODY$
DECLARE
qry text;
BEGIN
qry := 'SELECT last_name, AVG(purchase_size)
FROM purchases
WHERE last_name = ANY($1)
GROUP BY last_name'
RETURN QUERY EXECUTE qry USING last_names;
END;
$BODY$
Run Code Online (Sandbox Code Playgroud)
但我在这里看到两个问题:
当我这样做时,这当前返回零行:
SELECT avg_purchases($${'Brown','Smith','Jones'}$$);
Run Code Online (Sandbox Code Playgroud)我错过了什么?
这有效:
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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
Run Code Online (Sandbox Code Playgroud)
或者(更新 - 带美元报价的例子):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
Run Code Online (Sandbox Code Playgroud)
有关如何引用字符串文字的更多信息:
在PostgreSQL中插入带单引号的文本
您不需要动态SQL.
虽然你可以把它包装成一个plpgsql函数(这可能很有用),但是一个简单的SQL函数就可以正常工作了.
你有类型不匹配.
avg()可能是numeric保持精确的结果.我转而float8使它工作,这只是一个别名double precision(你也可以使用).如果您需要完美的精度,请numeric改用.GROUP BY last_name想要一个普通的textOUT参数而不是text[].VARIADIC数组是一种有用的输入类型.如果您的客户端更容易,您还可以使用VARIADIC允许将数组作为元素列表传递的输入参数:
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;
Run Code Online (Sandbox Code Playgroud)
呼叫:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
Run Code Online (Sandbox Code Playgroud)
或者(以美元报价):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Run Code Online (Sandbox Code Playgroud)
请注意,标准Postgres 最多只允许100个元素.这是在编译时通过预设选项确定的:
max_function_args (integer)报告函数参数的最大数量.它由
FUNC_MAX_ARGS构建服务器时的值决定.默认值为100个参数.
当前缀为关键字时,您仍然可以使用数组表示法调用它VARIADIC:
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
Run Code Online (Sandbox Code Playgroud)
对于更大的数组(100+),我也会unnest()在子查询中使用JOIN它,它往往会更好地扩展: