章: 第2章: 実務クエリ基礎
「ユーザーごとの投稿数」をPHP側でカウントしていませんか?
全投稿を取得してPHPの配列で count() するコードは、データが増えるほどメモリと処理時間を消費します。1万件のレコードを全件取得してアプリ側で集計するのは、DB本来の仕事をわざわざ横取りしている状態です。
GROUP BY と集計関数を使えば、DBが集計まで完結してくれます。 アプリには結果だけを渡せばよく、コードもシンプルになります。
GROUP BY で集計できる主な関数
GROUP BY はテーブルの行をグループ化し、各グループに対して集計関数を適用します。SELECT に書ける非集計列は、GROUP BY に書いたカラムのみという制約(ONLY_FULL_GROUP_BY)に注意が必要です。
主な集計関数の比較
| 関数 | 用途 | NULL の扱い |
COUNT(*) |
全行数をカウント | NULLの行も数える |
COUNT(col) |
特定列の非NULL行数 | NULLをスキップ |
SUM(col) |
合計値 | NULLを無視して計算 |
AVG(col) |
平均値 | NULLを除外して計算 |
MAX(col) |
最大値 | NULLを無視 |
MIN(col) |
最小値 | NULLを無視 |
チェックポイント:
COUNT(*)とCOUNT(col)は挙動が異なります。NULLを含むカラムを集計するときはCOUNT(col)を使い、NULL行を除外した件数を取得しましょう。意図せず全件カウントになるミスを防げます。
実際のコードのサンプル
SELECT user_id, COUNT(*) AS post_count, MAX(created_at) AS last_posted_at
FROM posts
GROUP BY user_id
ORDER BY post_count DESC;
まとめ & 次のステップ
- GROUP BY はテーブルの行をグループ化し、各グループに集計関数を適用する
- SELECT に書ける非集計列は GROUP BY に含めたカラムのみ(ONLY_FULL_GROUP_BY)
COUNT(*)(全行)とCOUNT(col)(非NULL行)は別物。NULLの扱いに注意する- アプリ側での集計ループはDB側のGROUP BYに置き換えることでパフォーマンスが改善する
次回は 「HAVING句の使い所」 を学びます。集計後の結果をさらに絞り込む HAVING と WHERE の使い分けを正しく理解します。