SQLで平均を求める方法|AVG関数の使い方と実務で失敗しないポイント
CONTENTS
「SQLで平均を出したいけど、思った値にならない…」
「NULLやJOINの影響で平均がズレる理由がわからない…」
「GROUP BYやHAVINGとの違いが曖昧で不安…」
このような悩みを持つ方は非常に多く、実務でも“平均値のズレ”がバグや誤った意思決定の原因になるケースは少なくありません。
本記事では、SQLの集計関数であるAVG関数の基本から実務での応用・落とし穴までを体系的に解説します。
この記事を読むことで、以下が理解できます。
- AVG関数の正しい使い方と構文
- NULL・JOIN・型による平均値のズレの原因
- WHERE / GROUP BY / HAVINGの使い分け
- 実務で必須の「平均の定義」と設計の考え方
SQL初心者から実務経験者まで、「平均の扱いでミスしないレベル」まで引き上げます。
SQLのAVG関数とは?基本構文と考え方
AVG関数の役割
AVGは、指定した列の平均値を算出するSQLの集計関数です。
SELECT AVG(age) FROM users;
この1行で、全ユーザーの平均年齢が取得できます。
ALLとDISTINCTの違い
AVG(age) -- 通常(ALL)
AVG(DISTINCT age) -- 重複除外
- ALL:すべての値を対象(デフォルト)
- DISTINCT:重複値を除外
⚠ 注意
DISTINCTは「人数」ではなく「値の種類」で平均が決まるため、
実務では意図しない結果になりやすいです。
AVG関数の戻り値と精度の注意点
平均は小数になる
整数カラムでも結果は小数になります。
例:
1, 2 → 平均 = 1.5
DBごとに表示精度が異なる
- MySQL:小数桁が長く出ることがある
- PostgreSQL:丸められることがある
👉 対策:明示的にROUNDを使う
SELECT ROUND(AVG(score), 2) FROM results;
NULLの扱い|平均がズレる最大の原因
AVGはNULLを無視する
80, 90, NULL → 平均 = 85
👉 NULLは「0ではない」ため、計算対象から除外されます。
全てNULLの場合
NULL, NULL → 結果 = NULL
SELECT COALESCE(AVG(score), 0) FROM results;
実務ポイント
- NULLは「未入力」か「対象外」かで意味が変わる
- 平均の定義を必ず明文化する
条件付き平均|WHEREの使い方
基本構文
SELECT AVG(score)
FROM results
WHERE class = 'A';
👉 クラスAだけの平均
よく使う条件例
-- 期間指定
WHERE created_at >= '2026-04-01'
AND created_at < '2026-05-01'
-- ステータス指定
WHERE status = 'completed'
実務ポイント
- WHEREは「集計前のフィルタ」
- 平均の母集団を定義する最重要ポイント
グループ別平均|GROUP BYの使い方
基本構文
SELECT department_id, AVG(age)
FROM users
GROUP BY department_id;
👉 部署ごとの平均年齢
ORDER BYで並び替え
ORDER BY AVG(age) DESC;
実務ポイント
- 粒度(グループの細かさ)で結果は大きく変わる
- 件数が少ないグループは信頼性が低い
HAVINGで平均条件を指定する
基本構文
SELECT dept, AVG(sales)
FROM orders
GROUP BY dept
HAVING AVG(sales) >= 100000;
WHEREとの違い
| 句 | 対象 |
|---|---|
| WHERE | 行 |
| HAVING | 集計結果 |
👉 平均に条件を付けるならHAVING
複数列の平均の扱い
各列の平均
SELECT AVG(score), AVG(point)
FROM results;
行単位の平均
SELECT AVG((score + point) / 2)
FROM results;
⚠ 注意
- NULLで計算が崩れる
- 単位や重みが揃っているか要確認
小数処理|切り捨て・四捨五入
切り捨て
SELECT TRUNCATE(AVG(score), 1);
四捨五入
SELECT ROUND(AVG(score), 2);
実務ポイント
- 表示用か計算用かを分ける
- 丸めは最後に行う
実務でよくある失敗パターン
① JOINで平均がズレる
SELECT AVG(users.age)
FROM users
JOIN orders ON users.id = orders.user_id;
👉 注文数が多い人ほど重くなる
対策
SELECT AVG(age)
FROM (
SELECT DISTINCT id, age FROM users
) t;
② DISTINCTの誤用
👉 値の重複を除外するだけで、行の重複ではない
③ 型による誤差
(score + point) / 2
👉 整数除算になる可能性
(score + point) / 2.0
④ 外れ値の影響
👉 平均は極端な値に弱い
代替指標
- 中央値
- パーセンタイル
信頼性の高い参考情報
- MySQL公式(集計関数)
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html - PostgreSQL公式(AVG)
https://www.postgresql.org/docs/current/functions-aggregate.html - SQL標準仕様(ISO SQL)
https://www.iso.org/standard/63555.html
👉 実務では「DBごとの差分確認」が必須です
まとめ
SQLのAVG関数はシンプルに見えて、実務では非常に奥が深い関数です。
重要ポイントを整理します。
- AVGはNULLを除外する
- WHEREで母集団を定義する
- GROUP BYで粒度を決める
- HAVINGで平均条件を指定する
- JOIN・型・外れ値に注意する
特に重要なのは、
👉 「平均の定義を業務視点で決めること」
です。
次にやるべきこと
- 実際のデータでAVGを試す
- JOINあり/なしで結果を比較する
- NULLや外れ値の影響を検証する
👉 このプロセスを回せるようになると、SQLの実務レベルは一気に上がります。
エンジニアとして次のステージへ
ここまで読んだ方は、単なるSQLの書き方ではなく、
「データをどう解釈し、どう設計するか」に関心があるはずです。
私たちのチームでは、
- データ分析基盤の設計
- 大規模データの最適化
- 検索・レコメンドのロジック開発
など、「SQLを武器に価値を生み出す開発」に本気で取り組んでいます。
もし、
「もっと実務レベルでSQLを使いこなしたい」
「データに強いエンジニアになりたい」
と感じているなら、ぜひ一度お話ししましょう。
あなたのその興味は、確実に強みになります。
学んだSQLを、実務で使えるスキルにしたい方へ
本記事ではSQLの基本的な考え方や使い方を解説しましたが、
「実務で使えるレベルまで身につけたい」と感じた方も多いのではないでしょうか。
SQLは、文法を理解するだけでなく、
- どんなデータ構造で使われるのか
- どんなクエリが現場で求められるのか
を意識して学ぶことで、実践力が大きく変わります。
そうした「実務を見据えたSQL学習」を進めたい方には、
完全無料で学べるプログラミングスクール ZeroCode PLUS という選択肢もあります。
- SQLを含むWeb・データベース系スキルを体系的に学べる
- 未経験者でも実務を意識したカリキュラム
- 受講料・教材費がかからない完全無料の学習環境
- 完全オンラインでスキマ学習
※学習内容や進め方を確認するだけでもOKです