SQLクエリをある程度書いている方であれば、WHERE句にはかなり精通しているのではないでしょうか。WHERE句は集計フィールドには影響しませんが、集計値に基づいてレコードをフィルタリングする方法があり、その目的でHAVING句が用いられます。このブログでは、HAVING句の仕組みと、SELECTクエリでの使用方法の例をいくつか紹介します。
集約とHAVING句
集約は、通常、グループ化と組み合わせて使用されます。SQLでは、GROUP BY句を使用して実現します。集約とグループ化を組み合わせることで、データに対する高レベルな洞察を得ることができます。例えば、eコマース企業は、一定期間の売上を追跡したい場合があります。
多くの場合、データセット全体にGROUP BY句を適用したくない場合があります。このような場合、GROUP BYコマンドと条件付きHAVING句を一緒に使用して、不要な結果をフィルタリングすることができます。WHERE句と同様に、HAVING句は1つ以上のフィルター条件を指定しますが、グループまたは集約に対して指定します。そのため、HAVING句は常にWHERE句とGROUP BY句の後、(オプションの)ORDER BY句の前に配置されます。
SELECT column_list FROM table_name WHERE where_conditions GROUP BY column_list HAVING having_conditions ORDER BY order_expression
実用的な例
HAVING句の動作をよりよく理解するために、Sakila Sample Databaseに対していくつかのSELECTクエリを実行してみましょう。
最初のクエリは、レンタル回数の多い顧客が上位に表示されるように、上位の映画レンタル者を降順に並べ替えたものです。リストをある程度短くするために、HAVING句を使用してレンタル回数が3回未満の顧客を削除します。
SELECT c.customer_id, c.first_name, c.last_name, COUNT(r.rental_id) AS total_rentals FROM customer AS c LEFT JOIN rental AS r ON c.customer_id = r.customer_id GROUP BY c.customer_id HAVING total_rentals >= 3 ORDER BY total_rentals DESC;
Navicat Premium でのクエリと最初のページの結果を以下に示します。
これらのレンタル回数から判断すると、リストをさらに絞り込むことができそうですね!
WHERE句とHAVING句の両方を使用した行のフィルタリング
GROUP BY句とORDER BY句がクエリの処理の異なる時点で適用されるのと同様に、WHERE句とHAVING句も異なる時点で適用されます。そのため、グループ化と集約の前後で結果をフィルタリングするために、両方をクエリに含めることができます。たとえば、WHERE句を追加して、結果を特定の年の前半に制限することができます。
SELECT c.customer_id, c.first_name, c.last_name, COUNT(r.rental_id) AS total_rentals FROM customer AS c LEFT JOIN rental AS r ON c.customer_id = r.customer_id WHERE r.rental_date BETWEEN '2005-01-01' AND '2005-06-30' GROUP BY c.customer_id HAVING total_rentals >= 3 ORDER BY total_rentals DESC;
ここでも、上記のクエリとNavicat Premium での最初のページの結果を以下に示します。
複数の条件の組み合わせ
WHERE句がANDキーワードとORキーワードを使用して複数の条件をサポートしているのと同様に、HAVING句も複数の条件をサポートしています。たとえば、HAVING句を以下のように変更することで、レンタル回数が特定の範囲内にある顧客を見つけることができます。
HAVING total_rentals >= 3 AND total_rentals <= 10
まとめ
今日のブログでは、HAVING句を使用してグループ化および集計されたフィールドをフィルタリングする方法を学びました。
Navicat Premium に興味がありますか?評価目的であれば、14日間完全に無料で試用できます!