導入
「商品が2つ以上あるカテゴリだけ見たい」――これは集計した結果に対する絞り込みです。ここで WHERE を使おうとすると、うまくいきません。集計の前と後では、絞り込みに使う道具が違うのです。この違いが分かると、SQL の各句が「どんな順で実行されるか」まで見通せるようになります。
説明
WHERE は「集計する前の、1行1行」を絞り込みます。一方、HAVING は「集計した後のグループ」を絞り込みます。
flowchart LR
F["FROM<br/>表を読む"] --> W["WHERE<br/>行を絞る(集計前)"]
W --> G["GROUP BY<br/>グループに分ける"]
G --> H["HAVING<br/>グループを絞る(集計後)"]
H --> S["SELECT<br/>列・集計を選ぶ"]
S --> O["ORDER BY<br/>並べ替える"]
この「FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY」という実行順序が、SQL 集計の背骨です。書く順番(SELECT が先頭)と、実際に処理される順番(FROM が先)が違う点に注目してください。
「商品が2つ以上あるカテゴリ」はこう書きます。
SELECT category_id, COUNT(*) AS 商品数
FROM products
GROUP BY category_id
HAVING COUNT(*) >= 2;
WHERE と HAVING は併用できます。順序どおり、「まず WHERE で行を絞ってから集計し、HAVING でグループを絞る」と流れます。たとえば「価格1000円以上の商品だけを対象に、平均価格が5000円を超えるカテゴリ」はこうです。
SELECT category_id, AVG(price) AS 平均
FROM products
WHERE price >= 1000
GROUP BY category_id
HAVING AVG(price) > 5000;
やってみよう
初期表示のクエリを実行し、商品が2つ以上あるカテゴリだけが残ることを確認しましょう。次に HAVING COUNT(*) >= 2 を WHERE COUNT(*) >= 2 に書き換えて実行し、エラーになることを見てください。「集計結果の絞り込みは HAVING」――これを体で覚えられます。
演習
orders を user_id ごとにまとめ、注文が2件以上ある会員の user_id と注文件数だけを取り出してください。
ヒント1を見る
グループ分けのあと、HAVING COUNT(*) >= 2 で集計結果を絞ります。
ヒント2を見る
SELECT user_id, COUNT(*) AS 件数 FROM orders GROUP BY user_id HAVING COUNT(*) >= 2;