複合条件クエリ演習
概要
- 日程: Day 1 / セッション 9
- 時間: 14:55-15:40
- 形式: 実習
- ゴール: 「給与40万以上の営業部社員を給与降順で並べる」のような複合条件のクエリを5本書ける
- 学習形式: ハンズオン実習(AIペアプログラミング)
導入(5分)
セッション7で「人を1つの条件で探す」、セッション8で「並べる・パターンで探す・範囲で探す」道具を覚えました。ここからはそれらを 組み合わせる 時間です。
実務でやってくるリクエストはほとんどが複合条件です。「営業部 かつ 給与40万以上の人を給与の高い順に」「Gmailアドレス 以外 の顧客」「在庫が少なくて かつ 単価が高い商品」——日本語でも「かつ」「または」「以外」が連なります。SQLの AND OR NOT がそれに対応します。
複合条件で気をつけるのは「優先順位」と「括弧」。算数の 2 + 3 × 4 で掛け算が先に来るのと同じで、SQLにも演算子の優先順位があります。今日はそこに注目して書いていきましょう。
本編(10分)
1. AND と OR の優先順位
AND は OR より先に評価されます。掛け算が足し算より優先されるのと同じ感覚です。
-- 営業部 かつ 給与40万以上、または 開発部
SELECT * FROM employees
WHERE department_id = 1 AND salary >= 400000
OR department_id = 2;
このSQLの意味は 「(営業部 かつ 給与40万以上) または (開発部)」 です。AND のほうが先にくっつくので、開発部の人は給与にかかわらず全員出てきます。
もし意図が違うなら、括弧で囲んで優先順位を明示します。
-- 「営業部または開発部」 かつ 給与40万以上
SELECT * FROM employees
WHERE (department_id = 1 OR department_id = 2)
AND salary >= 400000;
実務で複合条件を書くときは、自信がなくても 常に括弧をつける くらいの感覚で良いです。後から読み返すときも楽になります。
ここがポイント
AND>ORの優先順位(ANDが先)- 迷ったら括弧で明示
- 改行とインデントで視覚的に整える
2. NOT と否定の書き方
「○○以外」を表現するときは NOT、<>、NOT IN、NOT LIKE などを使います。
-- 営業部以外の社員
SELECT * FROM employees
WHERE department_id <> 1;
-- 営業部・開発部のどちらでもない社員
SELECT * FROM employees
WHERE department_id NOT IN (1, 2);
-- メアドが gmail.com で終わらない顧客
SELECT * FROM customers
WHERE email NOT LIKE '%@gmail.com';
たとえると、検索エンジンで「除外したいキーワードに - をつける」のと似ています。「あれは欲しい、でもあれは要らない」を一発で書けるのが NOT の役割です。
ここがポイント
<>または!=は等価でないNOT IN (...)は「リストのどれにも該当しない」NOT LIKEで「パターンに一致しない」
コラム
NOT を多用すると、SQLは急速に読みにくくなります。「営業部でも開発部でもなく、かつ給与が30万未満でもない人」のような条件は、書いたあなたが翌日読み返しても意味が分からなくなりがちです。プロのSQL書き職人は「肯定形で書けるならそうする」を信条にしています。たとえば「給与30万未満でない人」より「給与30万以上の人」のほうが、人間の頭にも素直に入ります。SQLは機械への命令でもありますが、半分はチームメイトへの手紙です。
💬 AIに聞いてみよう
- 「
ANDとORの優先順位を間違えそうで怖いです。常に括弧を書いておくのは過剰でしょうか?」 - 「
NOTを使った条件と、肯定で書いた条件、可読性ってどっちが上ですか?」 - 「演算子の優先順位を全部覚える必要ありますか?括弧で済ませるのはアリですか?」
実習・演習(25分)
課題
以下の5本を順に書いてください。書き上がったらそれぞれ実行し、結果の件数と数行のサンプルをメモに残します。
Q1. 給与が40万以上の営業部社員を、給与の降順で並べる
ヒント:WHERE salary >= 400000 AND department_id = 1 + ORDER BY salary DESC
Q2. メールアドレスが @example.com で終わる社員のうち、給与が35万円未満の人を給与の昇順で並べる
ヒント:LIKE '%@example.com' + AND salary < 350000 + ORDER BY salary ASC
Q3. customers テーブルから、メールアドレスが @gmail.com 以外の顧客を、顧客名の昇順で並べる
ヒント:NOT LIKE '%@gmail.com'(このsandboxにgmailは登場しないかもしれません。実行して「全件返ってくる」のが正解)
Q4. products テーブルから、電子機器(category_id = 1)またはオフィス用品(category_id = 2)のうち、価格が1万円以下の商品を、価格の昇順で並べる
ヒント:(category_id = 1 OR category_id = 2) AND price <= 10000 または category_id IN (1, 2) AND price <= 10000
Q5. employees テーブルから、入社日が 2019-01-01 〜 2021-12-31 で、給与が40万以上50万以下の社員を、入社日の昇順で並べる
ヒント:BETWEEN '2019-01-01' AND '2021-12-31' + AND salary BETWEEN 400000 AND 500000
成果物
- 5本のSQLクエリ(
.sqlファイルに整理) - 各クエリの結果件数と、上位3行のサンプル
- 「想定と違う結果になったQ」とその原因の分析(自分の言葉で1〜2行)
ヒント
- まず日本語で「何と何を AND でつなぐか、何と何を OR でつなぐか」を整理してからSQLを書く
- 括弧の位置に迷ったら 両方の書き方で実行して結果件数を比較。違いが出るところがまさに優先順位の効果
- AI に聞くときは「このSQLを書いて」ではなく「Q4を
INで書いた版とORで書いた版、両方見せて違いを説明して」のような問い方をすると深く学べる
まとめ(5分)
一言でまとめると「AND と OR は優先順位が違うから、迷ったら括弧。NOT は便利だけど読みにくくなりがちだから、肯定で書けるならそうする」。
今日のここまでで、employees / products / customers を 1テーブル単位 で柔軟に絞り込めるようになりました。複数テーブルを跨いだ操作(例:「営業部の社員それぞれの注文を集計する」)は明日のJOINで扱います。今日のラスト2セッションは、絞り込んだ後の 集計 —— 「数を数える、平均を出す、合計を出す」がテーマです。
🔄 振り返りチェック
WHERE a = 1 OR a = 2 AND b = 3は、どの条件をどう括った意味になりますか?- 「営業部以外」を3通り以上の書き方で表現できますか?
- 括弧をつけずに書いたSQLを後で読み返して、自分は2週間後にも意味を即座に把握できると思いますか?
補足資料
- 参考リンク: PostgreSQL: 演算子の優先順位
- 発展課題: 自分でビジネスシーンを1つ想像し、「○○部の××以上の社員を△△順で」というクエリを1本作って実行する
学習ガイド
想定される質問と回答例
| 質問 | ヒント |
|---|---|
IN と OR の連続、どちらが速い? |
多くの場面で IN のほうがDB最適化されている。可読性の意味でも IN を推奨 |
WHERE a = 1 AND a = 2 と書くと? |
「1かつ2」は両立しないので結果0件。エラーにはならない |
(salary >= 400000) AND (department_id = 1) のように両方括弧をつけても問題ない? |
全く問題ない。冗長だが意図が明確になるので教育上はむしろ良い |
BETWEEN と >= AND <= どっちを使う? |
単純な範囲なら BETWEEN のほうが短く意図が明確。境界を含めたくないときは >= AND < 等で書き分ける |
つまずきやすいポイント
| つまずきポイント | ヒント |
|---|---|
AND OR の優先順位を忘れる |
「ANDのほうが結びつきが強い(掛け算と同じ)」と覚える。迷ったら必ず括弧 |
| 全角のスペースが混入してエラー | エディタで全角空白を可視化する設定にしておく |
NOT LIKE '%gmail%' で意図しない除外 |
部分一致は「文字列のどこかに gmail があれば除外」。先頭・末尾を意識して %@gmail.com のように書く |
| 結果件数が0でデバッグできない | 条件を1つずつ外して WHERE を弱め、どの条件が0件にしているか切り分ける |
SELECT * で列が多すぎて結果が読みにくい |
検索に使った列だけ SELECT に並べる、または \x で拡張表示 |