[SQL] 条件で絞り込む(WHERE)
Contents
様々な条件を使ってデータを絞り込むWHERE
全てのデータを取ってくることは通常ないので、何かしら条件をつけて該当するレコードだけを取り出す方法を説明する。
基本ルールは簡単で、FROMの後に「WHERE 条件」を付ける。
SELECT * FROM テーブル 条件
やり方がたくさんあるが、最初に覚える必要はない。必要な時に「どうやればいいか」を考えてそれを実現する方法を探す。なので最初は一通りさらっと見て「こういうやり方もあるのか」ぐらい見ておくぐらいでよいだろう。
Excelでフィルタを使って絞り込みをするのをSQLという別の書き方をしている、と考えれば受け入れやすいだろう
サンプルデータ
次のファイルをDLしてコンソールにコピーする。
条件に一致するレコードを抽出する
男性(sexが1)になっているレコードを抽出する。
カラムsexが数値型の場合:
SELECT name,age FROM di_sql_sample01 WHERE sex=1
name | age |
斎藤 | 18 |
鈴木 | 35 |
佐藤 | 46 |
サンプルデータではsexは数値型になっているが、もし文字列型だったら
SELECT name,age FROM di_sql_sample01 WHERE sex='1'
と値の指定方法を変える必要がある。型によって値の指定方法が変わるのでエラーが起きたら真っ先に確認するところ。
複数の条件で絞り込む方法
条件が1つだけとは限らないので、数の条件を指定して全てにorどれかに当てはまるデータの取り方を解説する。
全ての条件を満たす(AND)
いくつかの条件を指定して、そのすべてに当てはまるレコードを取ってくるには条件文をANDで繋ぐ。Excelでいうと複数の列に条件を設定しているのと同じ。
SELECT * FROM di_sql_sample01 WHERE 条件1 AND 条件2
例えば「男性の佐藤さんの名前と年齢のレコード」であれば
SELECT name,age FROM di_sql_sample01 WHERE sex=1 AND name='佐藤'
id | name | age |
4 | 佐藤 | 46 |
範囲を指定する
ある値がXより大きい(以上)とYより小さい(以下)を組み合わせることで範囲を絞り込むこともできる。範囲についてはBETWEEN X AND Yという書き方もできるがこちらの方が汎用的(だと思う)。BETWEENについては後半で紹介する。例は年齢が20より大きく40より小さいレコードの抽出。
SELECT id,name,age FROM di_sql_sample01 WHERE age>=20 AND age<40
id | name | age |
1 | 佐藤 | 24 |
3 | 鈴木 | 35 |
5 | 高橋 | 20 |
6 | 田中 | 30 |
7 | 伊藤 | 31 |
条件のどれかにあてはまる(OR)
いくつかの条件があってそのうちのどれかにあてはまるレコードを抽出する場合はORでつなぐ。例えば「18歳か名前が佐藤」の場合は以下のようになる。
SELECT id,name,age FROM di_sql_sample01 WHERE age=18 OR name='佐藤'
id | name | age |
1 | 佐藤 | 24 |
2 | 斎藤 | 18 |
4 | 佐藤 | 46 |
ANDとORを組み合わせる
SELECT id,name,age,sex FROM di_sql_sample01 WHERE (id=1 OR age<40) AND sex=1
ANDとORを組み合わせることもできる。例は「idが1か年齢が40未満、かつ男性」。言い換えると「idが1で男性」または「40歳未満の男性」となる。前者は該当するレコードが無いので、後者のみの結果になる。
id | name | age | sex |
2 | 斎藤 | 18 | 1 |
3 | 鈴木 | 35 | 1 |
5 | 高橋 | 20 | 1 |
値を並べて書いて絞り込む(IN)
WHERE (条件を指定するカラム) IN (値)は複数の値を指定してそのいずれかと合致すればそのレコードを抽出する(1つでも使える)。複数の場合はカンマでつなぐ。 次の例はnameが斎藤か鈴木のレコードを抽出している。
SELECT id,name,age FROM di_sql_sample01 WHERE name IN ('斎藤' , '鈴木')
id | name | age |
2 | 斎藤 | 18 |
3 | 鈴木 | 35 |
INは全てをORでつないだ場合と同じ。どちらでもよいが、数が多ければ多いほどINを使う方がわかりやすい。
文字列の部分一致で絞り込む(LIKE)
LIKEで文字列に部分一致するかで抽出できる。
SELECT id,name,age FROM di_sql_sample01 WHERE name LIKE '%木%'
id | name | age | sex |
3 | 鈴木 | 35 | 1 |
nameに「木」を含むかどうか。「%」はワイルドカードと言い、「何でもよい」の意味。
SELECT id,name,age FROM di_sql_sample01 WHERE name LIKE '木%'
後ろだけに%を付けると「最初が木で始まるname」になる。この場合は0件。
SELECT id,name,age FROM di_sql_sample01 WHERE name LIKE %'木'
id | name | age | sex |
3 | 鈴木 | 35 | 1 |
前だけに%を付けると「最後が木で終わるname」になる。
NULLかどうかで絞り込む(IS NULL)
NULLとは「何も入っていない」という意味。0とは違う。あるカラムがNULLのレコードのみを抽出にはIS NULLを使う。
SELECT id,name,age FROM di_sql_sample01 WHERE installed_atIS NULL
id | name | age | sex |
3 | 鈴木 | 35 | 1 |
最初はNULLで特定の行動をとったらその時間を入れるなど頻繁に使うので慣れておこう。
今回のサンプルはinstalled_atなので、installed_at IS NULLとはインストールしていないユーザーのこと。
またエラーでデータが取れていないレコードを除外する際に「IS NOT NULL」=何かしらデータが入っているレコードを抽出する、というのも良く使う。否定文については最後に説明する。
NULLについてはこちらに別途まとめた。
〇〇したかどうかで絞り込む(TRUEとFALSE)
論理型(boolen型ともいう。ブーリアンと読む)の場合カラムの中には「TRUE」か「FALSE」が入っており、条件に指定する場合は「IS TRUE」「IS FALSE」を指定する。
購入した、インストールしたなど「~したか」の区別をするために使われる。そのカラムが「退会したか」なのか「退会していないか」によって指定する条件が変わるので何を意味しているか正確に把握すること。
サンプルのdeletedはTRUEが「削除した」になり、FALSEでは「削除されていない」になる。なので次の場合は「削除した会員」になる。
SELECT * FROM di_sql_sample01 WHERE カラム IS TRUE
id | name | age | sex |
4 | 佐藤 | 46 | 1 |
範囲を指定して絞り込む(BETWEEN)
BETWEEN X AND Yで「XとYの間にある」を指定できる。20歳以上40歳以下のレコードを取りたければ以下のようになる。
SELECT id,name,age FROM di_sql_sample01 WHERE age BETWEEN 20 AND 40
id | name | age |
1 | 佐藤 | 24 |
3 | 鈴木 | 35 |
5 | 高橋 | 20 |
6 | 田中 | 30 |
7 | 伊藤 | 31 |
BETWEENは=を含むので20歳や40歳を含みたくなければ「BETWEEN 21 AND 39」とすること。
またBETWEENは「X以上 AND Y以下」なので
SELECT id,name,age FROM di_sql_sample01 WHERE age>=20 AND age=<40
と書いても同じ結果になる。
否定(NOT)
今までは「条件に当てはまる」レコードを抽出してきたが、「条件に当てはまらない」レコードを抽出したいこともある。その場合は「NOT」を付けることで否定文になる。
NOT LIKE | パターンを含まない |
NOT BETWEEN | 範囲に含まれない |
NOT IN | 値のいずれにも一致しない |
IS NOT NULL | NULLではない |
IS NOT TRUE | TRUEではない |
IS NOT FALSE | FALSEではない |
等しくない(!=, <>)
ある値に等しくない、は書き方が2つある。どちらでもいい。上述のようにNULLは取れないので注意すること。
SELECT id,name,age FROM di_sql_sample01 WHERE name != '佐藤’
SELECT id,name,age FROM di_sql_sample01 WHERE name <> '佐藤’