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.カラム
みたいな書き方も可能です。
このカテゴリの最新記事
2024.07.29
【Laravel】共通オブジェクトをbladeファイルで利用する方法
                        
                                              
                          2025.02.20
【Linux】UbuntuのデフォルトのエディタをVimに変更する
                        
                                              
                          2025.08.28
pg_auto_failoverのインストールとセットアップ
                        
                                              
                          2024.09.26
情報セキュリティの学び直し – パスワード編