集計関数 COUNT/SUM/AVG/MAX/MIN
レビューは 100 件あるのに、平均の分母が 60 だった
レビューの表に 100 行入っています。「平均点は」と聞かれて AVG(score) を書き、返ってきた 4.2 をそのまま報告した。あとで「100 人の平均ですか」と確認されて、答えに詰まる。よくある事故です。
reviews テーブルの score 列は、点数を付けずコメントだけ残した人が空 (NULL) になっているとします。ここで数え方を 2 つ並べてみます。
SQL クエリ
SELECT
COUNT(*) AS row_count,
COUNT(score) AS scored_count,
AVG(score) AS avg_score
FROM reviews;| row_count | scored_count | avg_score |
|---|---|---|
| 100 | 60 | 4.2 |
COUNT(*) は行を数えます。中身が何であろうと、1 行は 1 行なので 100 です。COUNT(score) は score に値が入っている行だけを数えるので 60 です。そして AVG(score) の分母も 60 でした。4.2 は「100 人の平均」ではなく「点数を付けた 60 人の平均」だったわけです。
5つの関数を同じ形で使う
集計関数は、複数行の値を1つにまとめます。COUNT(*) は行数、SUM(列) は合計、AVG(列) は平均、MAX(列) は最大値、MIN(列) は最小値です。件数以外は、括弧に計算したい列名を書きます。
例えば payments テーブルの支払額 amount が100、200、300なら、次の結果は件数3、合計600、平均200、最大300、最小100の1行です。
SQL クエリ
SELECT
COUNT(*) AS payment_count,
SUM(amount) AS total_amount,
AVG(amount) AS average_amount,
MAX(amount) AS largest_amount,
MIN(amount) AS smallest_amount
FROM payments;AS の後ろは結果の列名です。式はカンマで区切り、最後の式にはカンマを付けません。演習では SELECT と FROM が用意されているので、集計式を5行書きます。
括弧の中が * か列名かで、意味が変わる
COUNT は、括弧の中に何を書くかで数える対象が変わります。* なら行そのもの、列名ならその列に値が入っている行です。SUM や AVG、MAX、MIN も同じで、値のない行は計算から外します。
この性質は、裏返すと列の埋まり具合を測る道具になります。
SQL クエリ
SELECT
COUNT(*) AS all_members,
COUNT(birthday) AS birthday_filled
FROM members;2 つの数字が離れているほど、その列は空のままです。集計を報告する前にこの形で 1 度確かめておくと、「平均が思ったより高い」といった相談の半分はここで説明が付きます。
1 行も無いとき、合計は 0 ではない
WHERE で絞った結果が 0 行だったとき、COUNT(*) は 0 を返します。ところが SUM は 0 ではなく空 (NULL) を返します。数える対象が 1 つもないので、合計という答え自体が存在しないからです。
合計 0 円のつもりで受け取った値が空で、アプリ側の計算が壊れる、という形で表に出ます。
SQL クエリ
SELECT COALESCE(SUM(amount), 0) AS total
FROM payments
WHERE paid_at >= DATE '2026-04-01';COALESCE は、左から順に見て最初に空でない値を返す関数です。金額の合計を必ず数値として受け取りたいときは、こうして包んでおきます。
テーブル構造
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
category VARCHAR(30) NOT NULL,
price INT NOT NULL,
stock INT NOT NULL
);
INSERT INTO products (id, name, category, price, stock) VALUES
(1, 'ノートPC', '家電', 128000, 5),
(2, 'マウス', '家電', 2980, 30),
(3, 'キーボード', '家電', 6800, 12),
(4, '小説A', '書籍', 1800, 50),
(5, '小説B', '書籍', 2200, 20),
(6, 'コーヒー豆', '食品', 1500, 40),
(7, '紅茶葉', '食品', 1200, 25);期待される出力
| cnt | total_price | avg_price | max_price | min_price |
|---|---|---|---|---|
| 7 | 144480 | 20640.000000000000 | 128000 | 1200 |