グループ化後に特化した条件の絞込みを行う(Having)

GROUP BY句でまとめたデータに対して条件を指定して絞り込みたい場合、
WHERE句では行えません。

たとえば、都道府県毎の平均体重に対して条件を絞りたい場合などです。

そこで登場するのが、HAVING句です。

以下は、平均体重が53キロ以上の都道府県を出力するときの例です。

mysql> select address,AVG(weight) from member group by address having AVG(weight) >= 53;
+---------+-------------+
| address | AVG(weight) |
+---------+-------------+
| NULL    |     55.0000 |
| 千葉  |     53.0000 |
| 東京  |     67.0000 |
+---------+-------------+
3 rows in set (0.00 sec)

~以外を表す NOT 演算子

条件文には、LIKE, IS NULL, IN, BETWEENなどの演算子がありますが、
これらの条件に合わなかった場合という意味のNOT演算子をしようすることが
できます。

LIKE演算子にNOTをつけた場合

mysql> select * from member where name LIKE 't%';
+----+--------+------+--------+---------+
| id | name   | age  | weight | address |
+----+--------+------+--------+---------+
|  1 | tanaka |   30 |     57 | 東京  |
|  6 | takai  |   25 |     63 | 千葉  |
|  7 | tadano |   26 |     43 | 千葉  |
+----+--------+------+--------+---------+

mysql> select * from member where name NOT LIKE 't%';
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  2 | suzuki   |   32 |     77 | 東京  |
|  3 | nakamura |   33 |     52 | 群馬  |
|  4 | miura    |   31 |     67 | 埼玉  |
|  5 | kimura   |   27 |     62 | 茨城  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 11 | saeki    |   29 |     49 | 埼玉  |
| 12 | ooyama   |   29 |     48 | 埼玉  |
| 13 | kamata   |   22 |     47 | 埼玉  |
| 14 | mizumoto |   35 |     55 | NULL    |
+----+----------+------+--------+---------+

IS NULL演算子にNOTをつけた場合

mysql> select * from member where address IS NULL;
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
| 14 | mizumoto |   35 |     55 | NULL    |
+----+----------+------+--------+---------+

mysql> select * from member where address IS NOT NULL;
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  1 | tanaka   |   30 |     57 | 東京  |
|  2 | suzuki   |   32 |     77 | 東京  |
|  3 | nakamura |   33 |     52 | 群馬  |
|  4 | miura    |   31 |     67 | 埼玉  |
|  5 | kimura   |   27 |     62 | 茨城  |
|  6 | takai    |   25 |     63 | 千葉  |
|  7 | tadano   |   26 |     43 | 千葉  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 11 | saeki    |   29 |     49 | 埼玉  |
| 12 | ooyama   |   29 |     48 | 埼玉  |
| 13 | kamata   |   22 |     47 | 埼玉  |
+----+----------+------+--------+---------+

BETWEEN演算子にNOTをつけた場合

mysql> select * from member where age between 31 AND 35;
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  2 | suzuki   |   32 |     77 | 東京  |
|  3 | nakamura |   33 |     52 | 群馬  |
|  4 | miura    |   31 |     67 | 埼玉  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 14 | mizumoto |   35 |     55 | NULL    |
+----+----------+------+--------+---------+

mysql> select * from member where age NOT between 31 AND 35;
+----+--------+------+--------+---------+
| id | name   | age  | weight | address |
+----+--------+------+--------+---------+
|  1 | tanaka |   30 |     57 | 東京  |
|  5 | kimura |   27 |     62 | 茨城  |
|  6 | takai  |   25 |     63 | 千葉  |
|  7 | tadano |   26 |     43 | 千葉  |
| 11 | saeki  |   29 |     49 | 埼玉  |
| 12 | ooyama |   29 |     48 | 埼玉  |
| 13 | kamata |   22 |     47 | 埼玉  |
+----+--------+------+--------+---------+

IN演算子にNOTをつけた場合

mysql> select * from member where weight IN (49, 51, 52, 55);
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  3 | nakamura |   33 |     52 | 群馬  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 11 | saeki    |   29 |     49 | 埼玉  |
| 14 | mizumoto |   35 |     55 | NULL    |
+----+----------+------+--------+---------+

mysql> select * from member where weight NOT IN (49, 51, 52, 55);
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  1 | tanaka   |   30 |     57 | 東京  |
|  2 | suzuki   |   32 |     77 | 東京  |
|  4 | miura    |   31 |     67 | 埼玉  |
|  5 | kimura   |   27 |     62 | 茨城  |
|  6 | takai    |   25 |     63 | 千葉  |
|  7 | tadano   |   26 |     43 | 千葉  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 12 | ooyama   |   29 |     48 | 埼玉  |
| 13 | kamata   |   22 |     47 | 埼玉  |
+----+----------+------+--------+---------+

複数条件での検索(AND, OR)

MySQLのWhere句で複数の条件を指定する

複数条件をつける場合は、”AND” か “OR” でつなげます。”AND”でつなげた場合は”かつ”の意味になり両方の条件に合致する必要があり、”OR”でつなげた場合は”または”の意味になりいずれかの条件に合致すればよいという意味になります。

年が32歳未満で、かつ、東京出身のメンバーを抽出する場合は以下のようにします。

mysql> SELECT * FROM member WHERE age<32 AND address="東京";
+----+--------+------+--------+---------+
| id | name   | age  | weight | address |
+----+--------+------+--------+---------+
|  1 | tanaka |   30 |     57 | 東京  |
+----+--------+------+--------+---------+
1 row in set (0.00 sec)

一方、ORを使った例として、体重が50キロ未満、または、茨城出身を抽出する場合は以下のようにします。

mysql> select * from member where weight < 50 OR address="茨城";
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  5 | kimura   |   27 |     62 | 茨城  |
|  7 | tadano   |   26 |     43 | 千葉  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 11 | saeki    |   29 |     49 | 埼玉  |
| 12 | ooyama   |   29 |     48 | 埼玉  |
| 13 | kamata   |   22 |     47 | 埼玉  |
+----+----------+------+--------+---------+
8 rows in set (0.00 sec)

条件の優先順位

条件が2つの場合は優先順位は関係ありませんが、3つ以上の条件がある場合優先順位によって
結果が変わる場合もあります。

たとえば、年齢が30以上、かつ、体重50以上、または、茨城出身とした場合、
捕らえ方が以下の二通りあります。

  1. 30歳以上、かつ、体重50以上のメンバー、と、茨城出身のメンバー
  2. 体重50以上、または、茨城出身のメンバーの中で、年齢が30以上のメンバー

以下のように丸括弧”()”をつけずに実行した場合 “AND” が優先されるため、この場合は
上記の1.に該当する結果となります。

mysql> select * from member where age >= 30 AND weight >= 50 OR address="茨城";

上記2.の結果が得たいときは、”OR”のほうを優先させる必要があるので、ORの方の式を”()”で
囲みます。

mysql> select * from member where age >= 30 AND (weight >= 50 OR address="茨城");
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  1 | tanaka   |   30 |     57 | 東京  |
|  2 | suzuki   |   32 |     77 | 東京  |
|  3 | nakamura |   33 |     52 | 群馬  |
|  4 | miura    |   31 |     67 | 埼玉  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
| 14 | mizumoto |   35 |     55 | NULL    |
+----+----------+------+--------+---------+

MySQLで’LIKE’演算子を用いて部分検索(あいまい検索)を行う

LIKE演算子を使用する

WHERE句での文字列条件を”=”で行うと完全一致したものしか検索できませんでした。
しかし、ある文章の中にある文字が含まれているかどうかを検索する場面、つまり部分検索をする場面が多々あります。
そのときは”=”では実現できません。そこで登場するのがこのLIKE演算子です。

以下は、name列が’ta’で始まる行のみを抽出します。

mysql> SELECT * FROM member WHERE name LIKE 'ta%';
+----+--------+------+--------+---------+
| id | name   | age  | weight | address |
+----+--------+------+--------+---------+
|  1 | tanaka |   30 |     57 | 東京  |
|  6 | takai  |   25 |     63 | 千葉  |
|  7 | tadano |   26 |     43 | 千葉  |
+----+--------+------+--------+---------+
3 rows in set (0.00 sec)

LIKE演算子は、上記のように’%’と組み合わせて使い、%の部分がワイルドカードとなて、
なんでもOKということになります。

  • ta% -> taで始まる場合に一致
  • %ta -> taでおある場合に一致
  • %ta% -> どこかにtaがある場合に一致

MySQLのBETWEEN演算子とIN演算子

BETWEEN演算子を使ってみる

MySQLではBETWEEN演算子というものがあり、WHERE句で使うことができます。
以下のようにすると、weigt列が60以上、かつ、70以下のメンバーを抽出します。

mysql> SELECT * FROM member WHERE weight BETWEEN 60 AND 70;
+----+--------+------+--------+---------+
| id | name   | age  | weight | address |
+----+--------+------+--------+---------+
|  4 | miura  |   31 |     67 | 埼玉  |
|  5 | kimura |   27 |     62 | 茨城  |
|  6 | takai  |   25 |     63 | 千葉  |
+----+--------+------+--------+---------+
3 rows in set (0.00 sec)

IN演算子を使ってみる

MySQLではIN演算子というものもあり、WHERE句で使うことができます。
address列が’東京’、または、’茨城’のメンバーを抽出する。

mysql> SELECT * FROM member WHERE address IN ('東京', '茨城');
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  1 | tanaka   |   30 |     57 | 東京  |
|  2 | suzuki   |   32 |     77 | 東京  |
|  5 | kimura   |   27 |     62 | 茨城  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
+----+----------+------+--------+---------+
6 rows in set (0.00 sec)

これは、"OR"句を使っても実現できます。

mysql> SELECT * FROM member WHERE address='東京' OR address='茨城';
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  1 | tanaka   |   30 |     57 | 東京  |
|  2 | suzuki   |   32 |     77 | 東京  |
|  5 | kimura   |   27 |     62 | 茨城  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
| 10 | suzuki   |   31 |     51 | 茨城  |
+----+----------+------+--------+---------+
6 rows in set (0.00 sec)

MySQLの条件文(WHERE句)の使い方 Vol.1

MySQLのWHERE句で条件の範囲指定をする

WHERE句には、完全一致以外にも検索方法があります。’>’, ‘=’, ‘<=' などの比較演算子を使用します。

たとえば、32歳以上のメンバーを検索する場合は以下のようにします。

mysql> SELECT * FROM member WHERE age>=32;
+----+----------+------+--------+---------+
| id | name     | age  | weight | address |
+----+----------+------+--------+---------+
|  2 | suzuki   |   32 |     77 | 東京  |
|  3 | nakamura |   33 |     52 | 群馬  |
|  8 | murakami |   35 |     42 | 茨城  |
|  9 | kikuchi  |   32 |     41 | 茨城  |
+----+----------+------+--------+---------+
4 rows in set (0.00 sec)

・比較演算子の一覧

x = y xとyが等しい
x y, x != y xとyが等しくない
x > y xとyが等しい
x >= y xがy以上
x > y xがyより大きい
x <= y xがy以下
x < y xがyより大きい