2025
September
18
postgresqlのPL/pgSQL関数で複数レコードをテーブル形式で出力する方法
postgresqlでSQLで取得したデータに対して加工したレコードを返したいという場合があるかと思います。
今回は関数で複数レコードをテーブル形式で出力する方法を紹介したいと思います。
テーブル
売上id | 顧客id |
A001 | K001 |
A002 | K003 |
売上id | 商品id | 個数 |
A001 | ringo | 10 |
A001 | mikan | 30 |
A002 | budo | 20 |
A002 | ringo | 50 |
商品id | 商品名 | 原価 |
ringo | りんご | 100 |
mikan | みかん | 300 |
budo | ぶどう | 500 |
ソースコード
CREATE OR REPLACE FUNCTION get_売上値引額 ()
RETURNS TABLE (
売上id VARCHAR,
商品id VARCHAR,
商品名 VARCHAR,
個数 VARCHAR,
原価 VARCHAR
)
AS $$
BEGIN
RETURN QUERY
SELECT
a.売上id,
a.商品id,
a.個数,
b.商品名,
b.原価
FROM 売上明細 AS a
INNER JOIN 商品マスタ AS b
ON a.商品id = b.商品id
;
END;
$$ LANGUAGE plpgsql;
SQL
SELECT *
FROM get_売上値引額();
結果
売上id | 商品id | 個数 | 商品名 | 原価 |
A001 | ringo | 10 | りんご | 100 |
A001 | mikan | 30 | みかん | 300 |
A002 | budo | 20 | ぶどう | 500 |
A002 | ringo | 50 | りんご | 100 |
説明
RETURNS TABLE内で宣言したカラムがレコードとして返されます。
RETURN QUERYでSQLのレコードを出力します。
データを加工した場合の出力方法
上の例ではSQLで取得したレコードをそのまま返しましたが、
次にデータを加工した場合の出力方法を紹介します。
例:個数が20個を超えていた場合、10%の値引きを明細に追加する
※売上idを指定して出力するようにしてます。
ソースコード
CREATE OR REPLACE FUNCTION "public"."get_売上値引額_売上id指定"("p_売上id" text)
RETURNS TABLE (
売上id VARCHAR,
商品id VARCHAR,
商品名 VARCHAR,
個数 VARCHAR,
原価 int4,
)
AS $BODY$
DECLARE
dblamt double;
cur cursor(p_売上id varchar) for SELECT * FROM 売上テーブル a WHERE a.売上id ~ p_売上id;
begin
dblamt := 0;
FOR cur_rec IN cur(p_売上id)
LOOP
売上id := cur_rec.売上id;
商品id := cur_rec.商品id;
商品名 := cur_rec.商品名;
個数 := cur_rec.個数;
原価 := cur_rec.原価;
if cur_rec.個数 > 20 then
dblamt := dblamt + ((cur_rec.原価 * cur_rec.個数) * 0.1);
end if;
RETURN NEXT;
END LOOP;
売上id := p_売上id;
商品id := 'nebiki';
商品名 := '値引';
個数 := 1;
原価 := dblamt * -1; --マイナスの金額に反転
RETURN NEXT;
RETURN;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000
SQL
SELECT *
FROM get_売上値引額_売上id指定('A001');
結果
売上id | 商品id | 個数 | 商品名 | 原価 |
A001 | ringo | 10 | りんご | 100 |
A001 | mikan | 30 | みかん | 300 |
A001 | nebiki | 1 | 値引 | -900 |
まとめ
データ加工してテーブルとして出力するという機能は知っているとかなり便利に使えると思いますので
参考になれば幸いです。
補足
関数がテーブルで返ってくるので
SELECT *
FROM テーブル a
LEFT JOIN function() b
ON a.カラム = b.カラム
みたいな書き方も可能です。
このカテゴリの最新記事
2025.01.31
C# LINQ:パフォーマンスと可読性を向上させる5つの重要トピック
2025.06.23
Autodesk Inventorでの図面作成をAPIで完全自動化、VBAとC#での実装方法も紹介
2024.12.19
名刺を画像から読み取り、ChatGPTで解析するシステムの構築 その2 -AWSとGCPの使い方も紹介
2023.04.21
PostgreSQLで翌営業日を取得する方法