AND/OR/NOTで複合条件
括弧を 1 組忘れると、要らない行が混ざる
「文具か雑貨で、かつ 500 円以上」という条件を、頭に浮かんだ順に並べて書いてみます。
SQL クエリ
-- 意図と違う結果になる
SELECT name, category, price
FROM products
WHERE category = '文具' OR category = '雑貨' AND price >= 500;返ってくるのは「文具のすべて」と「雑貨で 500 円以上」を足したものです。150 円のボールペンが結果に残ります。書いた本人は「文具か雑貨」でひとまとまりのつもりでも、SQL はそう読みません。
AND は OR より先に結ばれる
条件をつなぐ記号は 3 つあり、結ばれる強さが決まっています。強い順に NOT、AND、OR です。強いものから先にひとかたまりになるので、さきほどの式は次のように解釈されていました。
プレーンテキスト
category = '文具' OR (category = '雑貨' AND price >= 500)意図どおりにするには、先にまとめたい側を括弧で囲みます。
SQL クエリ
SELECT name, category, price
FROM products
WHERE (category = '文具' OR category = '雑貨')
AND price >= 500;括弧は、優先順位を覚えている人にとっても意味があります。読む人が優先順位を思い出さずに済むからです。OR と AND が同じ式に出てきたら括弧を付ける。 覚えるのはこれだけで足ります。
3 つのうち NOT がいちばん強いので、NOT category = '文具' AND price >= 500 は「文具ではない、かつ 500 円以上」と読まれます。NOT が後ろの AND までまとめてひっくり返すことはありません。ひとまとまり全体を否定したいなら、こちらも括弧で囲みます。
条件が 3 つ以上なら、行を分けて頭を揃える
条件が増えたときは、AND を行頭に置いて縦に揃えます。
SQL クエリ
SELECT name, category, price
FROM products
WHERE (category = '文具' OR category = '雑貨')
AND price BETWEEN 200 AND 1000
AND stock >= 10;1 行 1 条件になるので、条件を足すときも外すときも 1 行の増減で済みます。差分を見る人にも、どの条件が変わったのかがそのまま伝わります。
なお、同じ列に対する OR は IN で書き換えられます。category = '文具' OR category = '雑貨' は category IN ('文具', '雑貨') と同じ意味です。候補が増えるほど IN のほうが短くなり、括弧の付け忘れも起きません。
演習では customers から、2 つの都市のどちらかに住んでいて、かつ年齢の条件も満たす顧客を絞り込みます。どこを先にまとめるべきかを考えてから書いてください。
テーブル構造
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
city VARCHAR(30) NOT NULL,
age INT NOT NULL,
total_purchase INT NOT NULL
);
INSERT INTO customers (id, name, city, age, total_purchase) VALUES
(1, '田中 太郎', '東京', 28, 50000),
(2, '山田 花子', '大阪', 35, 120000),
(3, '佐藤 一郎', '東京', 42, 80000),
(4, '鈴木 次郎', '名古屋', 31, 30000),
(5, '田村 三郎', '東京', 25, 200000),
(6, '高橋 美咲', '大阪', 38, 150000),
(7, '伊藤 健太', '札幌', 29, 45000),
(8, '渡辺 由美', '東京', 45, 90000);期待される出力
| id | name | city | age |
|---|---|---|---|
| 2 | 山田 花子 | 大阪 | 35 |
| 3 | 佐藤 一郎 | 東京 | 42 |
| 6 | 高橋 美咲 | 大阪 | 38 |
| 8 | 渡辺 由美 | 東京 | 45 |