なっトク!

SQL--Whereとhavingの絞り込みの違い

2023-06-13

たすく

きょうは、絞り込みを「集計の前に置くか、後に置くか」で決めていきます

SQLで条件を絞るとき、最初に覚えるのがWHEREです。

まとめたあとに絞るのがHAVING。

教科書には、たいていそう書いてあります。

ところが、実際に書いていると、こう思う場面が出てきます。

「これ、どっちに書いてもいいのでは?」

同じ結果が出るなら、どっちでもよくない?

あかり
たすく

そう思いますよね。ただ、ここは3つに分かれるんです

ここは、大人の学び直しでつまずきやすい形をしています。

学生時代なら、教科書の区別を覚えれば正解でした。

いまは違います。

手元で動いてしまうと、「動いたから正しい」で通り過ぎるのです。

覚える区別と、使うときの判断は別物です。

教科書が教えてくれるのは、前者だけです。

なので、先に線を引いておきます。

結論:3つに分かれます

① 集計の前でしか絞れない条件

WHERE しかない

② 集計の後でしか絞れない条件

HAVING しかない

③ どちらにも書ける条件

WHERE のほうが軽い

実際に多いのは、①と②です。

「どっちでもいい」場面は、思っているより少ない。

ここが今回いちばん伝えたいところです。

まず、動く順番を押さえる

SQLは、書いた順には動きません。

おおよそ、この順で処理されます。

FROM → WHERE → GROUP BY → HAVING → SELECT

この並びが、そのまま答えになります。

WHEREは、まとめる前の1行1行を見ています。

HAVINGは、まとまった後のグループを見ています。

見ている相手が、そもそも違うのです。

HAVINGに書けない条件があります

たとえば、こう書きたくなったとします。

-- これは動きません
SELECT 日付, COUNT(社員名)
FROM   入退室管理
GROUP BY 日付
HAVING 事由区分 = '3'

エラーになります。

え、そもそも動かないんだ

あかり

理由は、さきほどの順番にあります。

HAVINGが動く時点で、行はすでに日付ごとにまとめられています。

1行ずつが持っていた事由区分は、その時点で消えているのです。

まとめたあとの世界に、まとめる前の列は残っていません。

HAVINGに書けるのは、GROUP BYに指定した列と、集計した結果だけ。

これは特定の製品の癖ではありません。

標準がそう決めています。

  • PostgreSQL … 集計されていない列は拒否されます
  • MySQL … いまは既定で拒否します

ただし、昔のMySQLはこれを通していました。

「前は書けたのに」という記憶がある方も、いるかもしれません。

通っていた頃も、結果は保証されていませんでした。

まとめた中のどの行の値が返るかは、決まっていないからです。

逆に、WHEREに書けない条件もあります

今度は逆の例です。

-- 10人以上いた日だけを出す
SELECT 日付, COUNT(社員名)
FROM   入退室管理
GROUP BY 日付
HAVING COUNT(社員名) >= 10

これはWHEREには書けません。

WHEREが動く時点では、まだ数えていないからです。

数えた結果で絞りたいなら、HAVINGしかない。

ここも、選択の余地はありません。

では、どちらにも書けるのはどんな条件か

絞りたい列が、GROUP BYに入っているときです。

日付でまとめて、日付で絞る。

この場合は、どちらにも書けます。

-- 軽い:減らしてから数える
SELECT 日付, COUNT(社員名)
FROM   入退室管理
WHERE  日付 >= '2026-04-01'
GROUP BY 日付

-- 重い:全部数えてから捨てる
SELECT 日付, COUNT(社員名)
FROM   入退室管理
GROUP BY 日付
HAVING 日付 >= '2026-04-01'

結果は同じです。

やっていることは、まるで違います。

答えが同じでも、通ってる道が違うんだ

あかり

1万件のうち、必要なのが100件だとします。

後者は、9,900件ぶんを数えてから捨てています。

数える作業そのものが、まるごと無駄になります。

同じ答えが出るなら、先に減らすほうが軽い。

たすく

そして、この差はデータが増えるほど開きます。小さいうちは気づけないんです

件数が少ないうちは、どちらで書いても一瞬で返ります。

だから、間違ったまま身につきます。

迷ったときの決め方

書きたい条件を見て、ひとつだけ自問してください。

「これは1行を見れば決まるか。

それとも、まとめないと決まらないか」

1行で決まるなら、WHERE。

まとめないと決まらないなら、HAVING。

これで、ほぼ間違えません。

順番を覚えるのではなく、相手が1行なのかグループなのかを見る。

そう捉え直すと、丸暗記が要らなくなります。

こういう差は、教科書に載りません

最後に、勉強のしかたの話を少しだけ。

WHEREとHAVINGの定義は、どの入門書にも載っています。

でも「どちらでも書けるときにどちらを選ぶか」は、あまり書かれていません。

答えが1つに決まらないからです。

学生時代の勉強は、答えのある問いを解くものでした。

社会に出てからの勉強は、答えが状況で変わる問いのほうが多くなります。

この違いは、受験勉強と社会に出てからの勉強は、何が違うのかで詳しく書きました。

そして、ここまで読んで全部覚える必要はありません。

覚えておくのは、順番の1行だけで足ります。

書く環境をまだ決めていない方は、SQLを書くソフトはどれを選べばいいのかのほうが先かもしれません。

  • この記事を書いた人
  • 最新記事

花丸たすく

▸「思考タイプ診断」で、働き方をスマートに
▸ あなたの価値を、現実を変える力へ
▸ 「IT戦略×データ分析×プロジェクトマネジメント」の知見
▸ 京都大学卒業後、教育・情報サービス系JTCなどでDX推進・データ分析・人材開発に従事