【エンジニア教材】MySQL編(1) WHERE句について (等号,不等号,BETWEEN,LIKE,IN,IS NULL)

# 【エンジニア教材】MySQL編(1) WHERE句について (等号,不等号,BETWEEN,LIKE,IN,IS NULL)

## まえがき

このドキュメントは社員やインターン生を教育するために作成したものですが、
ぜひ社外の人にも見ていただきたいと思い公開いたしました。

ちょこちょこ更新しますのでリクエストなどございましたらお気軽にお申し付け下さい。
体系的に書き進めていくのでリクエストしていただいたものについてすぐかける保証はございませんのでご理解とご了承のほどよろしくお願いいたします。
もし役に立ったら、いいね！やストックをしてもらえると励みになりますm(_ _)m

ちなみにプロフィールはこちら。
https://www.wantedly.com/users/1955894

# SELECT文でWHERE句を使って条件を絞ってレコードを取得する

今回はSELECT文でWHERE句を使って条件を絞ってレコードを取得するということをやって見ます。
はじめにデータを用意します。
今回はテスト用のデータをランダムに生成してくれるこちらのサイトを用いてデータをインポートしました。
http://kazina.com/dummy/index.html

同じデータを用いて試して見たいという方は次のSQLを実行してデータを入れて見てください。

```
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `name_kana` varchar(100) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `gender` varchar(10) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `blood_type` varchar(10) DEFAULT NULL,
  `birthday` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `users` (`id`, `name`, `name_kana`, `email`, `gender`, `age`, `blood_type`, `birthday`)
VALUES
	(1,'大村郁恵','おおむらいくえ','oomuraikue@example.com','F',39,'B','1978/1/23'),
	(2,'片岡寿明','かたおかとしあき','kataokatoshiaki@example.com','M',21,'A','1995/4/21'),
	(3,'岡島慎之介','おかじましんのすけ','okajimashinnosuke@example.com','M',20,'O','1997/2/4'),
	(4,'中田英嗣','なかたひでつぐ','nakatahidetsugu@example.com','M',23,'AB','1994/1/3'),
	(5,'藤村涼子','ふじむらりょうこ','fujimuraryouko@example.com','F',33,'O','1984/1/28'),
	(6,'相川一輝','あいかわかずき','aikawakazuki@example.com','M',35,'A','1981/8/18'),
	(7,'野崎由美子','のざきゆみこ','nozakiyumiko@example.com','F',12,'O','2005/1/20'),
	(8,'井口愛子','いぐちあいこ','iguchiaiko@example.com','F',18,'B','1998/8/6'),
	(9,'小森愛','こもりあい','komoriai@example.com','F',30,'O','1986/7/17'),
	(10,'那須由美子','なすゆみこ','nasuyumiko@example.com','F',13,'A','2003/10/5');
```

でははじめていきます。

## 全件全カラム取得する。

```
SELECT * FROM テーブル名;
```
SELECT文の基本中の基本です。
*というのが全てのカラムという意味になります。

実行例

```
mysql> select * from users;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```

## カラム名を指定して特定のカラムだけ全件取得する。
SELECT カラム名1 [,カラム名2, ...] FROM テーブル名;
全カラム取得する必要がないときはカラム名を指定してあげることができます。
複数カラムしていしたいときはカンマ区切りで指定します。

例：全レコードのidと名前の一覧だけ取得する。

```
mysql> select id,name from users;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | 大村郁恵        |
|  2 | 片岡寿明        |
|  3 | 岡島慎之介      |
|  4 | 中田英嗣        |
|  5 | 藤村涼子        |
|  6 | 相川一輝        |
|  7 | 野崎由美子      |
|  8 | 井口愛子        |
|  9 | 小森愛          |
| 10 | 那須由美子      |
+----+-----------------+
10 rows in set (0.00 sec)
```

## WHERE句を用いて特定の条件に一致するものを全件取得する。
WHERE句をある程度一般化して表現するとしたら次のようになります。
```SELECT 取得したい情報 from テーブル名 WHERE 条件;```
WHERE句ではさまざま条件を指定することができます。
たとえば、nameが大村郁恵のレコードを取得したいときは次のようになります。

例：nameが大村郁恵のレコードを取得する。

```
mysql> SELECT * FROM users WHERE name = "大村郁恵";
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
| id | name         | name_kana             | email                  | gender | age  | blood_type | birthday  |
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵     | おおむらいくえ        | oomuraikue@example.com | F      |   39 | B          | 1978/1/23 |
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
1 row in set (0.00 sec)
```

このように特定のカラムが特定の値と一致するという条件を指定したいときは
WHERE句では「カラム名 = 値」とすればよいことがわかります。
今回は基本的な例を紹介するため「カラム名 = 値」としましたが、
「カラム名1 = カラム名2」や「値1 = 値2」など、
ちゃんと条件式としての体裁を守っていれば自由に書けます。

条件を複数指定したい時はANDでつなぎます。

例：gender（性別）がF（女性）、かつblood_type（血液型）がB（型）のレコードを取得する。

```
mysql> SELECT * FROM users WHERE gender = "F" AND blood_type = "B";
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
| id | name         | name_kana             | email                  | gender | age  | blood_type | birthday  |
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵     | おおむらいくえ        | oomuraikue@example.com | F      |   39 | B          | 1978/1/23 |
|  8 | 井口愛子     | いぐちあいこ          | iguchiaiko@example.com | F      |   18 | B          | 1998/8/6  |
+----+--------------+-----------------------+------------------------+--------+------+------------+-----------+
2 rows in set (0.00 sec)
```

## 不等号などを用いた条件でレコードを取得する。
上では「=」を用いましたが、他の演算子もSQLで使用することができます。

例：20歳以上のレコードを全件取得する。

```
mysql> SELECT * FROM users WHERE age >= 20;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
7 rows in set (0.00 sec)
```

他にもこのような演算子を使用することができます。
気になる方は試して見てください。

| 名前 | 説明 |
|:-:|:-:|
|  = |  等しいかどうかを検査します。 |
| !=, <>  | 等しくないかどうかを検査します。  |
| >  | より大きいかどうかを検査します。  |
| >=  | 	より大きいかまたは等しいかを検査します。  |
| <  |  より小さいかどうかを検査します。 |
| <=  |  より小さいかまたは等しいかを検査します。 |

## BETWEENを用いた条件でレコードを取得する。
○○以上○○以下という条件はBETWEENを用いても書くことができます。
数字は下限、上限の順番でないとうまくいかないので注意しましょう。


例：20歳以上30歳以下のレコードを全件取得する。

```
mysql> SELECT * FROM users WHERE age BETWEEN 20 AND 30;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
4 rows in set (0.00 sec)
```

不等号で書くとしたらこうなります。全く一緒の結果ですね。

```
mysql> SELECT * FROM users WHERE age >= 20 AND age <=30;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
4 rows in set (0.00 sec)
```

個人的にはANDが条件と条件の間にあるものなのかBETWEEN内にあるのかわかりにくくなってしまうため、BETWEENはあまり好んで使用しないです。
不等号かBETWEENかでパフォーマンスも変わる可能性があります。
気になる方は調べて見てください。

また、NOT BETWEENを用いれば○○未満あるいは○○より大きいという条件になります。

## LIKEを用いた条件でレコードを取得する。
LIKEを用いると部分一致で検索することができます。

例：emailに「ka」が含まれているレコードを全件取得する。

```
mysql> SELECT * FROM users WHERE email LIKE "%ka%";
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
4 rows in set (0.00 sec)
```

「%ka%」の「%」はワイルドカードといい、なんでもいい（なくてもいい）ことを表します。
したがって、「%ka%」はkaの前後はなんでもよいということなので、すなわち部分一致となります。
これがもし、「ka%」であればkaから始まるものという前方一致でも検索となりますし、
「%ka」であれば最後がkaで終わるものという後方一致での検索となることになります。

また、NOT LIKEとすると一致しなかったものが取得できます。


## IN句を用いた条件でレコードを取得する。
IN句を用いると条件で値を配列で指定することができます。

例：idが（2,3,5）の中に含まれているレコードを全件取得する。

```
mysql> SELECT * FROM users WHERE id IN (2,3,5);
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
3 rows in set (0.00 sec)
```

また、NOT INとすると含まれないものが取得できます。


## ORを用いた条件でレコードを取得する。
複数の条件を記述するときは今まではANDを用いていましたが、複数の条件のうち、片方が成り立っていればよいという場合もあると思います。
そのような場合にはANDではなく、ORで条件を繋ぎましょう。

例：ageが20未満あるいはblood_typeがBであるレコードを全件取得する。


```
mysql> SELECT * FROM users WHERE age < 20 OR blood_type = "B";
+----+-----------------+-----------------------+--------------------------+--------+------+------------+-----------+
| id | name            | name_kana             | email                    | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------+--------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵        | おおむらいくえ        | oomuraikue@example.com   | F      |   39 | B          | 1978/1/23 |
|  7 | 野崎由美子      | のざきゆみこ          | nozakiyumiko@example.com | F      |   12 | O          | 2005/1/20 |
|  8 | 井口愛子        | いぐちあいこ          | iguchiaiko@example.com   | F      |   18 | B          | 1998/8/6  |
| 10 | 那須由美子      | なすゆみこ            | nasuyumiko@example.com   | F      |   13 | A          | 2003/10/5 |
+----+-----------------+-----------------------+--------------------------+--------+------+------------+-----------+
4 rows in set (0.00 sec)
```

## IS NULLを用いた条件でレコードを取得する。
IS NULLを用いるとレコードのあるカラムに値が入っていないもののみを取得することができます。

例：nameがNULLとなっているレコードを全件取得する。（0件ヒット）

```
mysql> SELECT * FROM users WHERE name IS NULL;
Empty set (0.00 sec)
```

また、IS NOT NULLとするとNULLでないものを取得できます。
例：nameがNULLでないレコードを全件取得する。（0件ヒット）

```
mysql> SELECT * FROM users WHERE name IS NOT NULL;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```