SQLで合計値を求める方法とは?SUM関数の使い方と応用例を徹底解説

データベース・SQL

データベースを扱っていると、「今月の売上合計はいくら?」「各店舗の売上を比較したい」「商品カテゴリ別の販売数量を知りたい」といった場面がよくありますよね。

そんなときに活躍するのが、SQLの「SUM関数」です。SUM関数を使えば、数値の合計を簡単に計算できます。

でも、基本的な使い方だけでなく、条件を指定したり、グループ別に集計したりする方法も知っておくと、とても便利です。

この記事では、SUM関数の基本から応用まで、実際のビジネス場面でよく使われるパターンを、初心者の方でもわかるように丁寧に説明します。

スポンサーリンク
  1. SUM関数とは何か?基本的な仕組み
    1. SUM関数の役割
    2. サンプルデータで理解しよう
    3. 基本的なSUM関数の使用例
    4. わかりやすい列名をつける
    5. SUM関数が便利な場面
  2. WHERE句で条件付き合計を求める
    1. 条件を指定した合計の重要性
    2. 基本的な条件付き合計
    3. 日付範囲での集計
    4. 文字列条件での集計
    5. 複数条件を組み合わせた集計
    6. 数量と価格を使った売上計算
    7. 顧客別の購入合計
    8. 実用的な条件付き集計例
  3. GROUP BYでカテゴリ別合計を求める
    1. GROUP BYの基本概念
    2. サンプルデータの拡張
    3. 基本的なGROUP BY使用例
    4. 複数の集計値を同時に表示
    5. 日付でグループ化
    6. 複数の列でグループ化
    7. HAVING句で集計結果を絞り込み
    8. 実用的なGROUP BY活用例
    9. WHERE句とGROUP BYの組み合わせ
  4. NULL値の扱い方と注意点
    1. NULL値とSUM関数の関係
    2. NULL値の基本的な動作
    3. NULL値の問題点
    4. NULL値を0として扱う方法
    5. NULL値を考慮した実用的な計算
    6. NULL値チェックの重要性
    7. 実務での対処法
    8. よくある間違いと対処法
  5. SUM関数と他の集計関数の組み合わせ
    1. 集計関数の種類と役割
    2. 基本的な組み合わせ例
    3. カテゴリ別の詳細分析
    4. 時系列分析
    5. 顧客分析
    6. 商品分析
    7. 複雑な比率計算
    8. 前年同期比較
    9. パフォーマンス指標
    10. 在庫分析
    11. 実用的なダッシュボード用クエリ
  6. 実用的なSUM関数活用パターン
    1. ビジネス場面別の活用例
    2. ECサイトの売上分析
    3. 小売店の在庫管理
    4. 製造業の生産管理
    5. 飲食店の売上管理
    6. 不動産業の契約管理
    7. 教育機関の成績管理
    8. 医療機関の収益分析
    9. パフォーマンス最適化のコツ
  7. まとめ

SUM関数とは何か?基本的な仕組み

SUM関数の役割

SUM関数は、指定したカラム(列)の数値をすべて足し算してくれるSQL関数です。

まるで電卓の「合計」ボタンのような機能ですね。

基本的な構文

SELECT SUM(カラム名) FROM テーブル名;

サンプルデータで理解しよう

以下のような売上データ(ordersテーブル)があるとします:

ordersテーブル

idproduct_namepricequantitycustomer_idorder_date
1ノートPC8000011012025-06-01
2マウス200021022025-06-01
3キーボード500011032025-06-02
4モニター3000011012025-06-02
5USB ケーブル100031042025-06-03

基本的なSUM関数の使用例

全商品の価格合計

SELECT SUM(price) FROM orders;

実行結果

SUM(price)
----------
118000

計算過程:80000 + 2000 + 5000 + 30000 + 1000 = 118000

全商品の販売数量合計

SELECT SUM(quantity) FROM orders;

実行結果

SUM(quantity)
-------------
8

計算過程:1 + 2 + 1 + 1 + 3 = 8

わかりやすい列名をつける

AS を使って結果に名前をつける

SELECT SUM(price) AS 売上合計 FROM orders;

実行結果

売上合計
--------
118000

複数の合計を同時に表示

SELECT 
    SUM(price) AS 売上合計,
    SUM(quantity) AS 販売数量合計
FROM orders;

実行結果

売上合計 | 販売数量合計
---------|------------
118000   | 8

SUM関数が便利な場面

ビジネスでよく使われる例

  • 売上分析:日別、月別、年別の売上合計
  • 在庫管理:商品の総在庫数
  • 予算管理:部署別の予算合計
  • 顧客分析:顧客ごとの購入金額合計
  • 成績管理:学生の点数合計

SUM関数の基本がわかったところで、次は条件を指定して、必要なデータだけの合計を求める方法を学びましょう。

WHERE句で条件付き合計を求める

条件を指定した合計の重要性

実際の業務では、「すべてのデータの合計」よりも「特定の条件に合うデータの合計」を求めることの方が多いです。

WHERE句を使えば、必要なデータだけを絞り込んで合計できます。

基本的な条件付き合計

特定の日の売上合計

SELECT SUM(price) AS 今日の売上 
FROM orders 
WHERE order_date = '2025-06-01';

実行結果

今日の売上
----------
82000

(ノートPC 80000円 + マウス 2000円 = 82000円)

一定金額以上の商品の合計

SELECT SUM(price) AS 高額商品合計 
FROM orders 
WHERE price >= 10000;

実行結果

高額商品合計
------------
110000

(ノートPC 80000円 + モニター 30000円 = 110000円)

日付範囲での集計

特定期間の売上合計

SELECT SUM(price) AS 期間売上 
FROM orders 
WHERE order_date BETWEEN '2025-06-01' AND '2025-06-02';

今月の売上合計

SELECT SUM(price) AS 今月売上 
FROM orders 
WHERE order_date >= '2025-06-01' AND order_date < '2025-07-01';

今年の売上合計

SELECT SUM(price) AS 今年売上 
FROM orders 
WHERE YEAR(order_date) = 2025;

文字列条件での集計

特定商品の売上合計

SELECT SUM(price) AS PC関連売上 
FROM orders 
WHERE product_name LIKE '%PC%';

特定文字が含まれない商品の合計

SELECT SUM(price) AS PC以外売上 
FROM orders 
WHERE product_name NOT LIKE '%PC%';

複数条件を組み合わせた集計

AND条件:すべての条件を満たす

-- 6月2日の高額商品(10000円以上)の合計
SELECT SUM(price) AS 高額商品売上 
FROM orders 
WHERE order_date = '2025-06-02' AND price >= 10000;

OR条件:いずれかの条件を満たす

-- PCまたはモニターの売上合計
SELECT SUM(price) AS PC関連売上 
FROM orders 
WHERE product_name LIKE '%PC%' OR product_name LIKE '%モニター%';

数量と価格を使った売上計算

実際の売上金額(単価×数量)

SELECT SUM(price * quantity) AS 実売上合計 
FROM orders;

実行結果

実売上合計
----------
121000

計算過程

  • ノートPC: 80000 × 1 = 80000
  • マウス: 2000 × 2 = 4000
  • キーボード: 5000 × 1 = 5000
  • モニター: 30000 × 1 = 30000
  • USBケーブル: 1000 × 3 = 3000
  • 合計: 122000円

顧客別の購入合計

特定顧客の購入合計

SELECT SUM(price * quantity) AS 顧客購入合計 
FROM orders 
WHERE customer_id = 101;

購入金額が高い顧客のデータ

SELECT SUM(price * quantity) AS 高額顧客合計 
FROM orders 
WHERE customer_id IN (101, 102, 103);

実用的な条件付き集計例

今日の売上と昨日の売上を比較

-- 今日の売上
SELECT SUM(price * quantity) AS 今日売上 
FROM orders 
WHERE DATE(order_date) = CURDATE();

-- 昨日の売上
SELECT SUM(price * quantity) AS 昨日売上 
FROM orders 
WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);

営業時間内の売上

SELECT SUM(price * quantity) AS 営業時間売上 
FROM orders 
WHERE TIME(order_date) BETWEEN '09:00:00' AND '18:00:00';

季節商品の売上分析

-- 冬物商品の売上
SELECT SUM(price * quantity) AS 冬物売上 
FROM orders 
WHERE product_name LIKE '%コート%' 
   OR product_name LIKE '%マフラー%' 
   OR product_name LIKE '%手袋%';

WHERE句を使った条件指定により、必要なデータだけを効率的に集計できます。次は、カテゴリや部署別など、グループごとの合計を求める方法を学びましょう。

GROUP BYでカテゴリ別合計を求める

GROUP BYの基本概念

GROUP BYを使うと、データを特定の基準でグループ分けして、それぞれのグループごとに合計を計算できます。これは、カテゴリ別の売上分析や部署別の実績集計などで、非常によく使われる機能です。

サンプルデータの拡張

より実用的な例にするため、商品カテゴリを追加したテーブルを考えてみましょう:

orders_detailテーブル

idproduct_namecategorypricequantityorder_date
1ノートPCPC8000012025-06-01
2マウスPC200022025-06-01
3キーボードPC500012025-06-02
4デスク家具3000012025-06-02
5椅子家具1500022025-06-03
6本棚家具2500012025-06-03

基本的なGROUP BY使用例

カテゴリ別の売上合計

SELECT 
    category AS カテゴリ,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY category;

実行結果

カテゴリ | 売上合計
---------|----------
PC       | 89000
家具     | 95000

計算過程

  • PCカテゴリ: (80000×1) + (2000×2) + (5000×1) = 89000
  • 家具カテゴリ: (30000×1) + (15000×2) + (25000×1) = 95000

複数の集計値を同時に表示

カテゴリ別の詳細分析

SELECT 
    category AS カテゴリ,
    COUNT(*) AS 商品数,
    SUM(quantity) AS 販売数量,
    SUM(price * quantity) AS 売上合計,
    AVG(price) AS 平均単価
FROM orders_detail
GROUP BY category;

実行結果

カテゴリ | 商品数 | 販売数量 | 売上合計 | 平均単価
---------|--------|----------|----------|----------
PC       | 3      | 4        | 89000    | 29000.00
家具     | 3      | 4        | 95000    | 23333.33

日付でグループ化

日別売上合計

SELECT 
    order_date AS 注文日,
    SUM(price * quantity) AS 日別売上
FROM orders_detail
GROUP BY order_date
ORDER BY order_date;

実行結果

注文日     | 日別売上
-----------|----------
2025-06-01 | 84000
2025-06-02 | 35000
2025-06-03 | 65000

月別売上集計

SELECT 
    DATE_FORMAT(order_date, '%Y-%m') AS 年月,
    SUM(price * quantity) AS 月間売上
FROM orders_detail
GROUP BY DATE_FORMAT(order_date, '%Y-%m');

複数の列でグループ化

カテゴリ別・日別の売上分析

SELECT 
    category AS カテゴリ,
    order_date AS 注文日,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY category, order_date
ORDER BY category, order_date;

実行結果

カテゴリ | 注文日     | 売上合計
---------|------------|----------
PC       | 2025-06-01 | 84000
PC       | 2025-06-02 | 5000
家具     | 2025-06-02 | 30000
家具     | 2025-06-03 | 65000

HAVING句で集計結果を絞り込み

GROUP BYで集計した結果に対して条件を指定するには、WHERE句ではなくHAVING句を使います。

売上が50000円以上のカテゴリのみ表示

SELECT 
    category AS カテゴリ,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY category
HAVING SUM(price * quantity) >= 50000;

実行結果

カテゴリ | 売上合計
---------|----------
PC       | 89000
家具     | 95000

商品数が2個以上のカテゴリ

SELECT 
    category AS カテゴリ,
    COUNT(*) AS 商品数,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY category
HAVING COUNT(*) >= 2;

実用的なGROUP BY活用例

店舗別売上ランキング

SELECT 
    store_name AS 店舗名,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY store_name
ORDER BY SUM(price * quantity) DESC;

営業担当者別実績

SELECT 
    sales_person AS 営業担当,
    COUNT(*) AS 受注件数,
    SUM(price * quantity) AS 売上合計,
    AVG(price * quantity) AS 平均受注額
FROM orders_detail
GROUP BY sales_person
ORDER BY 売上合計 DESC;

時間帯別売上分析

SELECT 
    HOUR(order_datetime) AS 時間帯,
    COUNT(*) AS 注文件数,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY HOUR(order_datetime)
ORDER BY 時間帯;

四半期別売上推移

SELECT 
    YEAR(order_date) AS 年,
    QUARTER(order_date) AS 四半期,
    SUM(price * quantity) AS 売上合計
FROM orders_detail
GROUP BY YEAR(order_date), QUARTER(order_date)
ORDER BY 年, 四半期;

WHERE句とGROUP BYの組み合わせ

今年のカテゴリ別売上

SELECT 
    category AS カテゴリ,
    SUM(price * quantity) AS 今年売上
FROM orders_detail
WHERE YEAR(order_date) = 2025
GROUP BY category;

高額商品(10000円以上)のカテゴリ別分析

SELECT 
    category AS カテゴリ,
    COUNT(*) AS 高額商品数,
    SUM(price * quantity) AS 高額商品売上
FROM orders_detail
WHERE price >= 10000
GROUP BY category;

GROUP BYを使いこなせるようになると、データの傾向や特徴を把握するのがとても楽になります。次は、NULL値がある場合の注意点を学びましょう。

NULL値の扱い方と注意点

NULL値とSUM関数の関係

SUM関数を使うときに注意が必要なのが、NULL値の扱いです。NULL値があるカラムを集計する場合、思わぬ結果になることがあります。

NULL値の基本的な動作

NULLを含むサンプルデータ

idproduct_namepricequantitydiscount
1ノートPC8000015000
2マウス20002NULL
3キーボード50001500
4モニターNULL11000
5USBケーブル10003NULL

基本的なSUM関数の動作

-- 価格の合計(NULLは無視される)
SELECT SUM(price) AS 価格合計 FROM products;

実行結果

価格合計
--------
88000

(80000 + 2000 + 5000 + 1000 = 88000、NULLのモニターは除外)

割引額の合計

SELECT SUM(discount) AS 割引合計 FROM products;

実行結果

割引合計
--------
6500

(5000 + 500 + 1000 = 6500、NULLは除外)

NULL値の問題点

1. 件数とSUMの不一致

SELECT 
    COUNT(*) AS 全件数,
    COUNT(price) AS 価格件数,
    SUM(price) AS 価格合計
FROM products;

実行結果

全件数 | 価格件数 | 価格合計
-------|----------|----------
5      | 4        | 88000

全部で5件あるのに、価格が設定されているのは4件だけです。

2. 平均値の計算への影響

-- NULLを無視した平均
SELECT AVG(discount) AS 割引平均 FROM products;
-- 結果: 2166.67 (6500 ÷ 3件)

-- 全件を対象とした場合の期待値
-- 6500 ÷ 5件 = 1300 とは異なる

NULL値を0として扱う方法

COALESCE関数を使用

-- NULLを0に置き換えて合計
SELECT SUM(COALESCE(discount, 0)) AS 割引合計 FROM products;

実行結果

割引合計
--------
6500

IFNULL関数を使用(MySQL)

SELECT SUM(IFNULL(discount, 0)) AS 割引合計 FROM products;

ISNULL関数を使用(SQL Server)

SELECT SUM(ISNULL(discount, 0)) AS 割引合計 FROM products;

NULL値を考慮した実用的な計算

実際の支払金額を計算

SELECT 
    product_name,
    price,
    COALESCE(discount, 0) AS 割引額,
    (price - COALESCE(discount, 0)) AS 実支払額
FROM products
WHERE price IS NOT NULL;

実行結果

product_name | price | 割引額 | 実支払額
-------------|-------|--------|----------
ノートPC     | 80000 | 5000   | 75000
マウス       | 2000  | 0      | 2000
キーボード   | 5000  | 500    | 4500
USBケーブル  | 1000  | 0      | 1000

カテゴリ別の割引率分析

SELECT 
    category,
    COUNT(*) AS 商品数,
    COUNT(discount) AS 割引設定数,
    SUM(COALESCE(discount, 0)) AS 割引合計,
    AVG(COALESCE(discount, 0)) AS 平均割引額
FROM products
GROUP BY category;

NULL値チェックの重要性

NULL値の件数を確認

SELECT 
    COUNT(*) AS 全件数,
    COUNT(price) AS 価格設定済み,
    COUNT(*) - COUNT(price) AS 価格未設定,
    COUNT(discount) AS 割引設定済み,
    COUNT(*) - COUNT(discount) AS 割引未設定
FROM products;

NULL値がある行を特定

-- 価格が未設定の商品
SELECT * FROM products WHERE price IS NULL;

-- 割引が未設定の商品
SELECT * FROM products WHERE discount IS NULL;

-- 価格または割引が未設定の商品
SELECT * FROM products WHERE price IS NULL OR discount IS NULL;

実務での対処法

1. データ入力時の制約

-- テーブル作成時にNOT NULL制約を設定
CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    product_name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,  -- NULL不可
    discount DECIMAL(10,2) DEFAULT 0  -- デフォルト値0
);

2. 集計前のデータクリーニング

-- 価格が設定されている商品のみで集計
SELECT 
    category,
    SUM(price) AS カテゴリ別売上
FROM products
WHERE price IS NOT NULL
GROUP BY category;

3. NULL値を明示的に処理

-- 売上から割引を引いた実売上
SELECT 
    SUM(price * quantity - COALESCE(discount * quantity, 0)) AS 実売上
FROM orders;

よくある間違いと対処法

間違い:NULL値を考慮しない集計

-- 問題のあるクエリ
SELECT 
    AVG(price) AS 平均価格,
    SUM(price) / COUNT(*) AS 平均価格2
FROM products;
-- 結果が異なる場合がある

正しい:NULL値を明示的に処理

-- 正しいクエリ
SELECT 
    AVG(COALESCE(price, 0)) AS 平均価格,
    SUM(COALESCE(price, 0)) / COUNT(*) AS 平均価格2
FROM products;
-- 同じ結果になる

NULL値の扱いを理解することで、正確な集計結果を得ることができます。次は、SUM関数と他の集計関数を組み合わせた応用的な使い方を学びましょう。

SUM関数と他の集計関数の組み合わせ

集計関数の種類と役割

SUM関数は他の集計関数と組み合わせることで、より詳細で有用な分析ができます。主要な集計関数を覚えておきましょう。

主要な集計関数

関数役割
SUM()合計値SUM(price)
COUNT()行数・件数COUNT(*)
AVG()平均値AVG(price)
MAX()最大値MAX(price)
MIN()最小値MIN(price)

基本的な組み合わせ例

売上の基本統計情報

SELECT 
    COUNT(*) AS 注文件数,
    SUM(price * quantity) AS 売上合計,
    AVG(price * quantity) AS 平均注文額,
    MAX(price * quantity) AS 最高注文額,
    MIN(price * quantity) AS 最低注文額
FROM orders;

実行結果

注文件数 | 売上合計 | 平均注文額 | 最高注文額 | 最低注文額
---------|----------|------------|------------|------------
5        | 122000   | 24400.00   | 80000      | 3000

カテゴリ別の詳細分析

商品カテゴリ別の包括的分析

SELECT 
    category AS カテゴリ,
    COUNT(*) AS 商品数,
    SUM(price) AS 価格合計,
    AVG(price) AS 平均価格,
    MAX(price) AS 最高価格,
    MIN(price) AS 最低価格,
    SUM(quantity) AS 販売数量合計,
    SUM(price * quantity) AS 売上合計
FROM orders
GROUP BY category
ORDER BY 売上合計 DESC;

実行結果

カテゴリ | 商品数 | 価格合計 | 平均価格  | 最高価格 | 最低価格 | 販売数量合計 | 売上合計
---------|--------|----------|-----------|----------|----------|--------------|----------
PC       | 3      | 87000    | 29000.00  | 80000    | 2000     | 4            | 89000
家具     | 2      | 45000    | 22500.00  | 30000    | 15000    | 3            | 75000

時系列分析

月別売上トレンド

SELECT 
    DATE_FORMAT(order_date, '%Y-%m') AS 年月,
    COUNT(*) AS 注文件数,
    SUM(price * quantity) AS 月間売上,
    AVG(price * quantity) AS 月間平均注文額,
    COUNT(DISTINCT customer_id) AS 購入顧客数
FROM orders
GROUP BY DATE_FORMAT(order_date, '%Y-%m')
ORDER BY 年月;

週別売上比較

SELECT 
    WEEK(order_date) AS 週番号,
    DAYOFWEEK(order_date) AS 曜日,
    COUNT(*) AS 注文件数,
    SUM(price * quantity) AS 日別売上,
    AVG(price * quantity) AS 平均注文額
FROM orders
GROUP BY WEEK(order_date), DAYOFWEEK(order_date)
ORDER BY 週番号, 曜日;

顧客分析

顧客別購入統計

SELECT 
    customer_id AS 顧客ID,
    COUNT(*) AS 注文回数,
    SUM(price * quantity) AS 累計購入額,
    AVG(price * quantity) AS 平均注文額,
    MAX(price * quantity) AS 最高注文額,
    MIN(order_date) AS 初回注文日,
    MAX(order_date) AS 最終注文日
FROM orders
GROUP BY customer_id
ORDER BY 累計購入額 DESC;

顧客ランク別分析

SELECT 
    CASE 
        WHEN 累計購入額 >= 100000 THEN 'VIP'
        WHEN 累計購入額 >= 50000 THEN 'ゴールド'
        WHEN 累計購入額 >= 20000 THEN 'シルバー'
        ELSE 'ブロンズ'
    END AS 顧客ランク,
    COUNT(*) AS 顧客数,
    AVG(累計購入額) AS 平均購入額,
    SUM(累計購入額) AS ランク別売上合計
FROM (
    SELECT 
        customer_id,
        SUM(price * quantity) AS 累計購入額
    FROM orders
    GROUP BY customer_id
) AS customer_summary
GROUP BY 
    CASE 
        WHEN 累計購入額 >= 100000 THEN 'VIP'
        WHEN 累計購入額 >= 50000 THEN 'ゴールド'
        WHEN 累計購入額 >= 20000 THEN 'シルバー'
        ELSE 'ブロンズ'
    END
ORDER BY 平均購入額 DESC;

商品分析

商品別売上ランキング

SELECT 
    product_name AS 商品名,
    COUNT(*) AS 注文回数,
    SUM(quantity) AS 総販売数量,
    SUM(price * quantity) AS 売上合計,
    AVG(quantity) AS 平均注文数量,
    MAX(quantity) AS 最大注文数量
FROM orders
GROUP BY product_name
ORDER BY 売上合計 DESC
LIMIT 10;

価格帯別売上分析

SELECT 
    CASE 
        WHEN price < 5000 THEN '5000円未満'
        WHEN price < 20000 THEN '5000円以上20000円未満'
        WHEN price < 50000 THEN '20000円以上50000円未満'
        ELSE '50000円以上'
    END AS 価格帯,
    COUNT(*) AS 商品数,
    SUM(quantity) AS 販売数量,
    SUM(price * quantity) AS 売上合計,
    AVG(price) AS 平均価格
FROM orders
GROUP BY 
    CASE 
        WHEN price < 5000 THEN '5000円未満'
        WHEN price < 20000 THEN '5000円以上20000円未満'
        WHEN price < 50000 THEN '20000円以上50000円未満'
        ELSE '50000円以上'
    END
ORDER BY 売上合計 DESC;

複雑な比率計算

カテゴリ別売上シェア

SELECT 
    category AS カテゴリ,
    SUM(price * quantity) AS カテゴリ売上,
    (SUM(price * quantity) * 100.0 / (SELECT SUM(price * quantity) FROM orders)) AS 売上シェア率
FROM orders
GROUP BY category
ORDER BY カテゴリ売上 DESC;

実行結果

カテゴリ | カテゴリ売上 | 売上シェア率
---------|--------------|-------------
PC       | 89000        | 72.95
家具     | 33000        | 27.05

前年同期比較

月別前年同期比

SELECT 
    DATE_FORMAT(order_date, '%m') AS 月,
    SUM(CASE WHEN YEAR(order_date) = 2025 THEN price * quantity ELSE 0 END) AS 今年売上,
    SUM(CASE WHEN YEAR(order_date) = 2024 THEN price * quantity ELSE 0 END) AS 前年売上,
    (SUM(CASE WHEN YEAR(order_date) = 2025 THEN price * quantity ELSE 0 END) - 
     SUM(CASE WHEN YEAR(order_date) = 2024 THEN price * quantity ELSE 0 END)) AS 売上差額,
    ROUND(
        (SUM(CASE WHEN YEAR(order_date) = 2025 THEN price * quantity ELSE 0 END) - 
         SUM(CASE WHEN YEAR(order_date) = 2024 THEN price * quantity ELSE 0 END)) * 100.0 / 
        NULLIF(SUM(CASE WHEN YEAR(order_date) = 2024 THEN price * quantity ELSE 0 END), 0), 
        2
    ) AS 成長率
FROM orders
WHERE YEAR(order_date) IN (2024, 2025)
GROUP BY DATE_FORMAT(order_date, '%m')
ORDER BY 月;

パフォーマンス指標

営業効率分析

SELECT 
    sales_person AS 営業担当,
    COUNT(*) AS 商談件数,
    COUNT(CASE WHEN status = 'completed' THEN 1 END) AS 成約件数,
    (COUNT(CASE WHEN status = 'completed' THEN 1 END) * 100.0 / COUNT(*)) AS 成約率,
    SUM(CASE WHEN status = 'completed' THEN price * quantity ELSE 0 END) AS 売上合計,
    AVG(CASE WHEN status = 'completed' THEN price * quantity END) AS 平均成約額
FROM orders
GROUP BY sales_person
ORDER BY 売上合計 DESC;

在庫分析

商品回転率分析

SELECT 
    p.product_name AS 商品名,
    p.stock AS 現在庫数,
    COALESCE(SUM(o.quantity), 0) AS 月間販売数,
    CASE 
        WHEN p.stock > 0 THEN ROUND(COALESCE(SUM(o.quantity), 0) / p.stock, 2)
        ELSE NULL 
    END AS 在庫回転率,
    COALESCE(SUM(o.price * o.quantity), 0) AS 月間売上
FROM products p
LEFT JOIN orders o ON p.product_name = o.product_name 
    AND o.order_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY p.product_name, p.stock
ORDER BY 在庫回転率 DESC;

実用的なダッシュボード用クエリ

経営ダッシュボード用の総合指標

SELECT 
    '売上' AS 項目,
    SUM(price * quantity) AS 今日,
    (SELECT SUM(price * quantity) FROM orders WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)) AS 昨日,
    (SELECT SUM(price * quantity) FROM orders WHERE MONTH(order_date) = MONTH(CURDATE()) AND YEAR(order_date) = YEAR(CURDATE())) AS 今月
FROM orders
WHERE DATE(order_date) = CURDATE()

UNION ALL

SELECT 
    '注文件数' AS 項目,
    COUNT(*) AS 今日,
    (SELECT COUNT(*) FROM orders WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)) AS 昨日,
    (SELECT COUNT(*) FROM orders WHERE MONTH(order_date) = MONTH(CURDATE()) AND YEAR(order_date) = YEAR(CURDATE())) AS 今月
FROM orders
WHERE DATE(order_date) = CURDATE()

UNION ALL

SELECT 
    '平均注文額' AS 項目,
    AVG(price * quantity) AS 今日,
    (SELECT AVG(price * quantity) FROM orders WHERE DATE(order_date) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)) AS 昨日,
    (SELECT AVG(price * quantity) FROM orders WHERE MONTH(order_date) = MONTH(CURDATE()) AND YEAR(order_date) = YEAR(CURDATE())) AS 今月
FROM orders
WHERE DATE(order_date) = CURDATE();

実用的なSUM関数活用パターン

ビジネス場面別の活用例

実際のビジネスでSUM関数がどのように使われているか、具体的なパターンを紹介します。

ECサイトの売上分析

日別売上と目標達成率

SELECT 
    DATE(order_date) AS 日付,
    COUNT(*) AS 注文件数,
    SUM(price * quantity) AS 日別売上,
    100000 AS 日別目標,
    ROUND((SUM(price * quantity) / 100000) * 100, 1) AS 目標達成率
FROM orders
WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY DATE(order_date)
ORDER BY 日付 DESC;

送料を含む実売上計算

SELECT 
    DATE(order_date) AS 日付,
    SUM(price * quantity) AS 商品売上,
    SUM(shipping_fee) AS 送料合計,
    SUM(price * quantity + shipping_fee) AS 実売上,
    SUM(CASE WHEN shipping_fee = 0 THEN 1 ELSE 0 END) AS 送料無料件数
FROM orders
GROUP BY DATE(order_date)
ORDER BY 日付 DESC;

小売店の在庫管理

商品別の収益性分析

SELECT 
    product_name AS 商品名,
    SUM(quantity) AS 販売数量,
    AVG(cost_price) AS 平均仕入価格,
    AVG(selling_price) AS 平均販売価格,
    SUM((selling_price - cost_price) * quantity) AS 粗利合計,
    ROUND(AVG((selling_price - cost_price) / selling_price * 100), 1) AS 粗利率
FROM sales
GROUP BY product_name
HAVING SUM(quantity) > 0
ORDER BY 粗利合計 DESC;

カテゴリ別の在庫回転状況

SELECT 
    category AS カテゴリ,
    SUM(current_stock) AS 現在庫総数,
    SUM(sales_quantity) AS 月間販売数,
    ROUND(SUM(sales_quantity) / NULLIF(SUM(current_stock), 0), 2) AS 在庫回転率,
    SUM(dead_stock_value) AS デッドストック金額
FROM inventory_summary
GROUP BY category
ORDER BY 在庫回転率 DESC;

製造業の生産管理

生産ライン別効率分析

SELECT 
    production_line AS 生産ライン,
    SUM(production_quantity) AS 生産数量,
    SUM(defect_quantity) AS 不良品数,
    ROUND((1 - SUM(defect_quantity) / NULLIF(SUM(production_quantity), 0)) * 100, 2) AS 良品率,
    SUM(production_cost) AS 生産コスト,
    ROUND(SUM(production_cost) / NULLIF(SUM(production_quantity), 0), 2) AS 単位コスト
FROM production_data
WHERE production_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY production_line
ORDER BY 良品率 DESC;

飲食店の売上管理

時間帯別売上分析

SELECT 
    CASE 
        WHEN HOUR(order_time) BETWEEN 6 AND 10 THEN '朝食'
        WHEN HOUR(order_time) BETWEEN 11 AND 14 THEN 'ランチ'
        WHEN HOUR(order_time) BETWEEN 15 AND 17 THEN 'おやつ'
        WHEN HOUR(order_time) BETWEEN 18 AND 22 THEN 'ディナー'
        ELSE 'その他'
    END AS 時間帯,
    COUNT(*) AS 注文件数,
    SUM(order_amount) AS 売上合計,
    AVG(order_amount) AS 平均客単価,
    SUM(customer_count) AS 来客数
FROM restaurant_orders
WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY 
    CASE 
        WHEN HOUR(order_time) BETWEEN 6 AND 10 THEN '朝食'
        WHEN HOUR(order_time) BETWEEN 11 AND 14 THEN 'ランチ'
        WHEN HOUR(order_time) BETWEEN 15 AND 17 THEN 'おやつ'
        WHEN HOUR(order_time) BETWEEN 18 AND 22 THEN 'ディナー'
        ELSE 'その他'
    END
ORDER BY 売上合計 DESC;

不動産業の契約管理

営業担当者別成績

SELECT 
    sales_person AS 営業担当,
    COUNT(*) AS 契約件数,
    SUM(contract_amount) AS 契約金額合計,
    AVG(contract_amount) AS 平均契約額,
    SUM(commission) AS 手数料合計,
    ROUND(AVG(DATEDIFF(contract_date, first_contact_date)), 1) AS 平均成約日数
FROM real_estate_contracts
WHERE contract_date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
GROUP BY sales_person
ORDER BY 契約金額合計 DESC;

教育機関の成績管理

科目別成績統計

SELECT 
    subject AS 科目,
    COUNT(*) AS 受験者数,
    SUM(score) AS 得点合計,
    AVG(score) AS 平均点,
    MAX(score) AS 最高点,
    MIN(score) AS 最低点,
    SUM(CASE WHEN score >= 80 THEN 1 ELSE 0 END) AS 優秀者数,
    ROUND(SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END) / COUNT(*) * 100, 1) AS 合格率
FROM exam_results
WHERE exam_date >= '2025-04-01'
GROUP BY subject
ORDER BY 平均点 DESC;

医療機関の収益分析

診療科別売上分析

SELECT 
    department AS 診療科,
    COUNT(*) AS 患者数,
    SUM(medical_fee) AS 診療報酬合計,
    AVG(medical_fee) AS 平均診療費,
    SUM(insurance_amount) AS 保険請求額,
    SUM(patient_payment) AS 患者負担額,
    ROUND(AVG(treatment_time), 1) AS 平均診療時間
FROM medical_records
WHERE visit_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY department
ORDER BY 診療報酬合計 DESC;

パフォーマンス最適化のコツ

効率的なSUM関数の使用

-- 推奨:必要なカラムのみをSELECT
SELECT 
    category,
    SUM(price * quantity) AS 売上
FROM orders
WHERE order_date >= '2025-06-01'
GROUP BY category;

-- 非推奨:不要なカラムも取得
SELECT 
    *,
    SUM(price * quantity) AS 売上
FROM orders
WHERE order_date >= '2025-06-01'
GROUP BY category;

インデックスを活用した高速化

-- WHERE句やGROUP BYで使用するカラムにインデックス作成
CREATE INDEX idx_order_date_category ON orders(order_date, category);

-- 効率的な集計クエリ
SELECT 
    category,
    DATE(order_date) AS 日付,
    SUM(price * quantity) AS 日別売上
FROM orders
WHERE order_date >= '2025-06-01'
GROUP BY category, DATE(order_date)
ORDER BY category, 日付;

まとめ

SQLのSUM関数は、データ分析と業務改善において欠かせない重要なツールです。この記事で学んだ内容を整理してみましょう。

SUM関数の基本ポイント

  • SUM関数は指定したカラムの数値を合計する
  • WHERE句で条件を指定して、必要なデータだけを集計
  • GROUP BYでカテゴリ別や期間別の集計が可能
  • NULL値は自動的に除外される(必要に応じてCOALESCE等で対処)

実用的な活用パターン

  • 売上分析:期間別、カテゴリ別、担当者別の売上集計
  • 在庫管理:商品別の販売数量や在庫回転率の計算
  • 顧客分析:購入額や購入回数による顧客セグメント
  • パフォーマンス分析:目標達成率や効率指標の算出

他の集計関数との組み合わせ

-- 包括的な分析例
SELECT 
    category AS カテゴリ,
    COUNT(*) AS 件数,
    SUM(price * quantity) AS 売上合計,
    AVG(price * quantity) AS 平均注文額,
    MAX(price) AS 最高単価,
    MIN(price) AS 最低単価
FROM orders
GROUP BY category;

コメント

タイトルとURLをコピーしました