[SQL] HAVING句とWHERE句の違い
今回はSQLの HAVING 句について解説する。
HAVING 句は WHERE 句と同様にデータのフィルタリングを行うが、その適用タイミングと対象が異なる。
SQL初学者が最もつまずきやすいポイントの一つである「WHERE と HAVING の使い分け」について、実例を交えて見ていく。
準備
本サイトではpythonのライブラリであるsqlite3とipython-sqlを利用して、Jupyter Notebook上でSQLを実行・解説する。 また、データフレームの表示には Polars を利用する。
github
- githubのjupyter notebook形式のファイルはこちら
google colaboratory
- google colaboratory で実行する場合はこちら
筆者の環境
筆者の環境である。
!sw_vers
ProductName: macOS
ProductVersion: 15.5
BuildVersion: 24F74
!python -V
Python 3.12.12
必要なライブラリを読み込む。
import sqlite3
import polars as pl
%load_ext sql
%config SqlMagic.feedback = True
%config SqlMagic.style = '_DEPRECATED_DEFAULT'
データの準備
サンプルとして、顧客ごとの注文データを格納した Orders テーブルを作成する。
import os
if os.path.exists("data.db"):
os.remove("data.db")
os.system("touch data.db")
os.system("chmod 664 data.db")
# データベース接続
%sql sqlite:///data.db
'Connected: @data.db'
%%sql
CREATE TABLE Orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER,
amount INTEGER
);
INSERT INTO Orders (customer_id, amount) VALUES
(1, 100),
(1, 200),
(2, 500),
(3, 100),
(3, 100),
(3, 100),
(4, 1000);
* sqlite:///data.db
Done.
7 rows affected.
[]
%%sql
SELECT * FROM Orders;
* sqlite:///data.db
Done.
| id | customer_id | amount |
|---|---|---|
| 1 | 1 | 100 |
| 2 | 1 | 200 |
| 3 | 2 | 500 |
| 4 | 3 | 100 |
| 5 | 3 | 100 |
| 6 | 3 | 100 |
| 7 | 4 | 1000 |
課題:注文合計金額が400以上の顧客を抽出する
顧客ごと(customer_id)に amount を合計し、その結果が400以上の顧客だけを表示したい。
間違い:WHERE句で集計結果をフィルタリングしようとする
以下のようなクエリはエラーになる。
SELECT
customer_id,
SUM(amount) as total_amount
FROM
Orders
WHERE
SUM(amount) >= 400
GROUP BY
customer_id;
理由: WHERE 句は 集計前 の行に対してフィルタリングを行うため、集計関数(SUM など)を条件に指定できないからである。
正解:HAVING句を使用する
集計後の結果に対してフィルタリングを行う場合は、HAVING 句を使用する。
query = """
SELECT
customer_id,
SUM(amount) as total_amount
FROM
Orders
GROUP BY
customer_id
HAVING
SUM(amount) >= 400;
"""
with sqlite3.connect("data.db") as conn:
df = pl.read_database(query, connection=conn)
display(df)
shape: (2, 2)
| customer_id | total_amount |
|---|---|
| 2 | 500 |
| 4 | 1000 |
解説:実行順序
SQLの実行順序を理解すると、違いが明確になる。
- FROM: 対象テーブルを選択
- WHERE: 行をフィルタリング(集計前)
- GROUP BY: グループ化
- HAVING: グループをフィルタリング(集計後)
- SELECT: 表示する列を選択
WHERE はグループ化の前に実行されるため、集計結果を知ることができない。
一方、HAVING はグループ化の後に実行されるため、集計結果に基づいてフィルタリングが可能である。
まとめ
- WHERE: 集計 前 の行を絞り込む。
- HAVING: 集計 後 のグループを絞り込む。
「集計結果に対して条件を指定したい場合は HAVING」と覚えておけば間違いない。