ray88’s diary

お仕事で困ったとき用の自分用の覚書

SQL 累計を求める

SQL 目次 - ray88’s diary
■部署A,部署B,部署C ごとに累計売上を抽出する

【方法1】
このSQLでは、SUM(amount) OVER (PARTITION BY section ORDER BY year, month)の部分で、セクションごとに年と月で並び替えた上でamountの累積和を計算しています。PARTITION BY句は、累積和を計算するためのグループを指定します。ORDER BY句は、累積和を計算するための順序を指定します。の結果として、各セクションの月ごとのamountの累積値が得られます。この結果を元に累積グラフを作成することができます

SELECT 
    year,
    month,
    section,
    SUM(amount) OVER (PARTITION BY section ORDER BY year, month) AS cumulative_amount
FROM 
    amount
ORDER BY 
    year, 
    month, 
    section;

【方法2】
ACCESSなどOVER関数が使用できない場合の対処
このSQLでは、外部のクエリで年、月、セクションごとのデータを選択し、内部のサブクエリでそれぞれのセクションの累積和を計算しています。サブクエリでは、対象のセクションと同じセクションで、対象の年月以前のデータの合計(累積和)を計算しています。これにより、各セクションの月ごとのamountの累積値が得られます。この結果を元に累積グラフを作成することができます。

SELECT 
    s.year,
    s.month,
    s.section,
    (SELECT SUM(sub.amount) FROM amount AS sub
     WHERE sub.section = s.section AND 
     (sub.year < s.year OR (sub.year = s.year AND sub.month <= s.month))) AS cumulative_amount
FROM 
    amount AS s
ORDER BY 
    s.year, 
    s.month, 
    s.section;

【テストデータ作成】

CREATE TABLE amount (
    year INT NOT NULL,
    month INT NOT NULL,
    section VARCHAR(50) NOT NULL,
    amount INT NOT NULL
);

INSERT INTO amount (year, month, section, amount) VALUES
(2022, 4, 'sectionA', 12000),
(2022, 4, 'sectionB', 13000),
(2022, 4, 'sectionC', 11000),
(2022, 5, 'sectionA', 12500),
(2022, 5, 'sectionB', 12600),
(2022, 5, 'sectionC', 11500),
(2022, 6, 'sectionA', 12300),
(2022, 6, 'sectionB', 13400),
(2022, 6, 'sectionC', 11250);