SQLの条件抽出構文としてWHEREがありますが、GROUP BYを用いてCOUNT,SUMなどの集計関数で算出した値をWHEREで絞り込むと意図した値になりません。GROUP BYで集計した結果にたいして条件指定で絞り込みたい場合はHAVING句を利用しないと適切に条件を抽出することができません。
SQLを始めたばかりの方や、慣れていない方はなぜ条件通りに抽出できないのか?HAVING句を知らないと悩むポイントです。強引に違う方法(WITH句やテーブル化など)を用いれば対応ができますが、非効率です。
そこで、本記事では、SQLのWHEREとHAVINGの違いを解説することで、なぜGROUP BY利用後にWHEREを利用すると適切な値が抽出されないのか?HAVINGがどういう仕組みなのかを解説いたします。
SQLのWHERE句とHAVING句で抽出した値の違い
例えば下記のような商品にたいして売上金額のみが書かれているデータがあるとします。商品数はAからCの3通りですが、売上金額が違うので5個のデータになっています。
PRODUCT | SALES |
---|---|
A | 100 |
B | 200 |
B | 300 |
C | 400 |
C | 500 |
このデータから商品毎の売上合計金額が500円以上のデータを抽出したいとします。WHERE句を用いたSQL文は下記。
SELECT 商品、SUM(SALES) AS SUMsales
FROM テーブルA
WHERE SALES >= 500
GROUP BY ALL
結果はCの500のみが抽出されます。今回のお題は「商品毎の売上合計金額」を抽出したいので、結果がことなります。
PRODUCT | SALES |
---|---|
C | 500 |
では、HAVING句を使ってかいてみます。
SELECT 商品、SUM(SALES) AS SUMsales
FROM テーブルA
GROUP BY ALL
HAVING SALES >= 500
結果です。
PRODUCT | SALES |
---|---|
B | 500 |
C | 900 |
商品毎に合計金額が集計された値にたいして、条件を絞り込んだ結果が抽出されました。
WHEREとHAVINGの書く順番に注意
SQL処理順が影響!集計関数GROUP BYの前がWHERE句で後がHAVING句
SQLはコード記載の順番で処理されておらず、下記順番で処理されています。この処理順番を意識してSQL文を書く必要があります。
集計関数GROUP BYの前にあるのがWHEREで後ろにあるのがHAVING
WHERE:集計(GROUP BY)される前にSQL処理されるので、集計後の値で絞り込むことができない。
HAVING:集計(GROUP BY)後にSQL処理されるので、集計後の値を絞り込める
- FROM
- WHERE
- GROUP BY
- HAVING
- SELECT
- ORDER BY
サンプルデータでWHERE句とHAVING句の違いを解説
下記データを例にコードをご紹介いたします。
■商品情報ファイル1
カテゴリ | 商品名 | 原価 | 個数 | 在庫金額 | 販売開始日 | 販売終了日 |
---|---|---|---|---|---|---|
1 | カビキラー | 1158 | 1 | 1158 | 2025/01/20 | 2025/03/20 |
カテゴリが1のものを対象に在庫金額合計を求め、金額合計が5,000円以上のものを集計するSQL文が下記。SQL文が処理される順番をコードに振りました。(#から右の文章)
select
商品名,sum(在庫金額) as 合計金額
from 商品情報ファイル #処理順1:利用テーブル
where カテゴリ = '1' #処理順2:抽出条件
group by 1 #処理順3:集計関数
having #処理順4:集計後の条件処理
合計金額 >5000
上記SQL文を実行すると下記のような集計結果がでてきます。group byで集計された値にたいして、havingを用いて5,000円以上の商品を抽出しています。
商品名 | 合計金額 |
---|---|
カビキラー | 10,000 |
石鹸 | 7,000 |
上記HAVING句をあえてWHERE句で書くと下記イメージです。下記の場合は抽出条件WHERE句のところにand 在庫金額 >5000と書きました。
処理順を見ると、where カテゴリ = ‘1’ and 在庫金額 >5000の後に集計関数group byが来るので、集計前の値で絞り込まれます。※WHERE句は1,000円が含まれません。
HAVING句の場合(5,000円以上抽出)
・1,000円
・6,000円
・8,000円
結果:15,000円
WHERE句の場合(5,000円以上抽出)
・1,000円
・6,000円
・8,000円
結果:14,000円
select
商品名,sum(在庫金額) as 合計金額
from 商品情報ファイル #処理順1:利用テーブル
where カテゴリ = '1' and 在庫金額 >5000 #処理順2:抽出条件
group by 1 #処理順3:集計関数
まとめ
SQLのWHERE句とHAVING句の違いについて解説しました。