如何在PostgreSQL中的函数中返回SELECT的结果?
我在PostgreSQL有这个功能,但我不知道如何返回查询的结果:
CREATE OR REPLACE FUNCTION wordFrequency(maxTokens INTEGER) RETURNS SETOF RECORD AS $$ BEGIN SELECT text,count(*),100 / maxTokens * count(*) FROM ( SELECT text FROM token WHERE chartype = 'ALPHABETIC' LIMIT maxTokens ) as tokens GROUP BY text ORDER BY count DESC END $$ LANGUAGE plpgsql; 但我不知道如何返回的查询结果在PostgreSQL函数内。 我发现返回类型应该是SETOF RECORD,对吧?但是返回命令是不正确的。 什么是正确的方法这样做?
使用
RETURN QUERY :
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int) RETURNS TABLE ( txt text -- visible as OUT parameter inside and outside function,cnt bigint,ratio bigint) AS $func$ BEGIN RETURN QUERY SELECT t.txt,count(*) AS cnt -- column alias only visible inside,(count(*) * 100) / _max_tokens -- I added brackets FROM ( SELECT t.txt FROM token t WHERE t.chartype = 'ALPHABETIC' LIMIT _max_tokens ) t GROUP BY t.txt ORDER BY cnt DESC; -- note the potential ambiguity END $func$ LANGUAGE plpgsql; 呼叫: SELECT * FROM word_frequency(123); 说明: >显式定义返回类型比简单地声明为记录更加实用。这样,您不必为每个函数调用提供列定义列表。 但请注意OUT参数cnt和同名的列别名之间的潜在命名冲突。在这种特殊情况下(RETURN QUERY SELECT …)Postgres以任何一种方式使用OUT参数上的列别名。这在其他上下文中可能是模糊的。有多种方法可以避免任何混淆: >使用SELECT列表中项的顺序位置:ORDER BY 2 DESC。例: > Select first row in each GROUP BY group? >重复表达式ORDER BY count(*)。 > Naming conflict between function parameter and result of JOIN with USING clause >不要使用“文本”和“计数”作为列名称。两者都是合法的在Postgres中使用,但“计数”是标准SQL中的一个reserved word和一个基本的函数名称,“文本”是一个基本的数据类型。可能导致混乱的错误。我在我的例子中使用txt和cnt。 替代 这是我认为你的查询应该实际上(计算每个令牌的相对份额): CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int) RETURNS TABLE ( txt text,abs_cnt bigint,relative_share numeric) AS $func$ BEGIN RETURN QUERY SELECT t.txt,t.cnt,round((t.cnt * 100) / (sum(t.cnt) OVER ()),2) -- AS relative_share FROM ( SELECT t.txt,count(*) AS cnt FROM token t WHERE t.chartype = 'ALPHABETIC' GROUP BY t.txt ORDER BY cnt DESC LIMIT _max_tokens ) t ORDER BY t.cnt DESC; END $func$ LANGUAGE plpgsql; 表达式sum(t.cnt)OVER()是一个window function.你可以使用一个CTE而不是子查询 – 漂亮,但是一个子查询通常在这种简单的情况下更便宜。 最后explicit
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |