使用RETURN QUERY
:
CREATE OR REPLACE FUNCTION word_frequency(_max_tokens int)
RETURNS TABLE (txt text -- also visible as OUT parameter inside 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; -- potential ambiguity
END
$func$ LANGUAGE plpgsql;
コール:
SELECT * FROM word_frequency(123);
説明:
単に戻り値の型をレコードとして宣言するよりも、明示的に定義する方がはるかに実用的です。これにより、すべての関数呼び出しで列定義リストを提供する必要がなくなります。RETURNS TABLE
それを行う1つの方法です。他にもあります。OUT
パラメータのデータ型は、クエリによって返されるものと正確に一致する必要があります。
OUT
パラメータの名前は慎重に選択してください。それらは関数本体のほとんどどこにでも表示されます。競合または予期しない結果を回避するために、同じ名前の列をテーブル修飾します。私の例では、すべての列に対してそれを行いました。
ただし、同じ名前のパラメーターと列エイリアスの間で名前が競合する可能性があることに注意してください。この特定のケース()では、Postgresはいずれかの方法でパラメータに対して列のエイリアスを使用します。ただし、これは他の状況ではあいまいになる可能性があります。混乱を避ける方法はいくつかあります。OUT
cnt
RETURN QUERY SELECT ...
OUT
- SELECTリスト内のアイテムの序数位置を使用します
ORDER BY 2 DESC
。例:
- 式を繰り返します
ORDER BY count(*)
。
- (ここでは適用外。)構成パラメーターを設定する
plpgsql.variable_conflict
か#variable_conflict error | use_variable | use_column
、関数で特殊コマンドを使用します。見る:
列名として「テキスト」または「カウント」を使用しないでください。Postgresではどちらも使用できますが、「count」は標準SQLの予約語であり、基本的な関数名であり、「text」は基本的なデータ型です。紛らわしいエラーが発生する可能性があります。私の例ではを使用txt
しcnt
ています。
;
ヘッダーに欠落していた構文エラーを追加しました。(_max_tokens int)
、ではない(int maxTokens)
- と入力した後の名前。
整数除算を処理する場合、丸め誤差を最小限に抑えるために、最初に乗算し、後で除算することをお勧めします。さらに良い:(numeric
または浮動小数点型)で作業します。下記参照。
オルタナティブ
これは、クエリが実際に次のようになるはずだと思います(トークンごとの相対シェアを計算する):
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 ()
はウィンドウ関数です。サブクエリの代わりにCTEを使用することもできますが、このような単純なケースでは、サブクエリの方が通常は安価です。
パラメータを使用する場合、または(パラメータを暗黙的に使用する場合)、最後の明示的なRETURN
ステートメントは必要ありません(ただし許可されます)。OUT
RETURNS TABLE
OUT
round()
2つのパラメーターを使用すると、numeric
型に対してのみ機能します。count()
サブクエリではbigint
結果が生成され、sum()
これbigint
によりnumeric
結果が生成されるため、numeric
数値が自動的に処理され、すべてが適切に配置されます。