はじめに
同じような機能を持っているけど使い分けをしっかりしていく必要があるWHERE句とHAVING句の使い分け方についてまとめてみました。
結論
結論からいうと、
WHERE句はテーブルにある行に対して「ある列の値がこの数値以上」などといった条件を指定し、HAVING句は集約関数などを使って集約したテーブルのデータに対しての条件を指定します。
つまり、WHERE句には「行に対する指定」
HAVING句には「グループに対する指定」
を行うというのが原則になります。
ここでいう「グループ」とは集約関数などによって集約された行の集まりという意味です。
つまり
WHERE句は「集約前のデータに対する指定」
HAVING句は「集約後のデータに対する指定」
に適用されます。
具体例
WHERE句の例
シナリオ: 社員データベースに、各社員の部署と給与が記録されています。部署ごとに給与が50,000円以上の社員のみを選択したい場合。
SELECT 部署, 名前, 給与
FROM 社員
WHERE 給与 >= 50000;
このクエリでは、WHERE句を使用して、給与が50,000円以上の各社員のデータを選択しています。WHERE句は各行に個別に適用され、指定された条件に一致する行のみが結果に含まれます。
HAVING句の例
シナリオ: 同じ社員データベースを使用し、部署ごとに平均給与が60,000円以上の部署のみを選択したい場合
SELECT 部署, AVG(給与) as 平均給与
FROM 社員
GROUP BY 部署
HAVING AVG(給与) >= 60000;
このクエリでは、まず社員を部署ごとにグループ化し、それぞれの平均給与を計算しています。HAVING句は、これらのグループに適用され、平均給与が60,000円以上の部署のみを結果として表示します。HAVING句は集約後のデータに対して条件を適用するために使用されます。
どちらにも書ける要素
集約キー(GROUP BY句で指定された列)に対する条件はHAVING句とWHERE句のどちらにも書くことができ、どちらに書いても同じ機能を持ちます。しかしながら集約キーに対する条件はWHERE句に書くべきであるという考え方があります。理由は2つあります。
- 集約キーに対する条件は「行に対する指定」なのでWHERE文に書くべき
- WHERE文に書いた方が処理速度が速くなる
1に関しては前述の役割の違いが理由です。
2に関してはまず、COUNT関数などの集約関数はテーブルのデータに対してソートをしていますが、このソート処理は比較的重い処理になります。WHERE句でデータに対して先にフィルタリングをしてあげると、処理が行われるデータ量が減少し、結果として集約処理が速くなります。
まとめ
・WHERE句は「行に対する条件」を書く
・HAVING句は「グループに対する条件」を書く
・集約キーに対する条件はWHERE句に書く