MySQLのNULL安全等価演算子(宇宙船演算子)
- MySQL
-
2022-10-11
今回はMySQLでのNULL安全等価演算子についてご紹介します。
NULL安全等価演算子とは<=>のことで、見た目が宇宙船に似ていることからSpaceship Operator(宇宙船演算子)とも言われます。
※他言語でもあるんですが、返り値が違ったりするのでご注意ください。
まず、値の比較について見ていきます。
1と1を等価演算子で比較します。
MySQL> SELECT 1 = 1; +-------+ | 1 = 1 | +-------+ | 1 | +-------+
結果は真の1となりました。
次は1と0を比較してみましょう。
MySQL> SELECT 1 = 0; +-------+ | 1 = 0 | +-------+ | 0 | +-------+
結果は偽の0となりました。
今後は1とNULLを比較してみます。
MySQL> SELECT 1 = NULL; +----------+ | 1 = NULL | +----------+ | NULL | +----------+
結果は偽の0となるかと思いきや、NULLとなりました。
NULL同士を比較するとどうでしょうか。
MySQL> SELECT NULL = NULL; +-------------+ | NULL = NULL | +-------------+ | NULL | +-------------+
結果はNULLとなりました。
1とNULLの場合は0、NULL同士の場合は1になって欲しいですよね。
そこで登場するのが、今回のNULL安全等価演算子(宇宙船演算子)です。
それを使うと次のようになります。
1とNULLの場合
SELECT 1 <=> NULL; +------------+ | 1 <=> NULL | +------------+ | 0 | +------------+
NULL同士の場合
SELECT NULL <=> NULL; +---------------+ | NULL <=> NULL | +---------------+ | 1 | +---------------+
ということで、まさに欲しい結果が返ってきてくれます。
続いてサンプルデータを用いて、実際の事例をご紹介します。
ここで例えば、2つのテーブルからデータを抽出するSQLを組むと仮定しましょう。
例として次のような適当なサンプルデータを用意しました。
mysql> SELECT * FROM sampleA; +----+--------+------+ | id | name | type | +----+--------+------+ | 1 | 赤井 | 1 | | 2 | 井田 | 2 | | 3 | 宇野 | NULL | | 4 | 江崎 | 1 | | 5 | 奥本 | 2 | +----+--------+------+ mysql> SELECT * FROM sampleB; +----+--------+------+ | id | name | type | +----+--------+------+ | 1 | 赤井 | 1 | | 2 | 井田 | 2 | | 3 | 宇野 | NULL | | 4 | 江崎 | 1 | | 5 | 奥本 | 2 | +----+--------+------+
sampleAとsampleBは全く同じ内容です。
ここで、sampleAとsampleBのnameとtypeを結び付けてデータを抽出してみます。
SELECT * FROM sampleA
-> INNER JOIN sampleB
-> ON sampleA.name = sampleB.name
-> AND sampleA.type = sampleB.type;
+----+------+------+----+------+------+
| id | name | type | id | name | type |
+----+------+------+----+------+------+
| 1 | 赤井 | 1 | 1 | 赤井 | 1 |
| 2 | 井田 | 2 | 2 | 井田 | 2 |
| 4 | 江崎 | 1 | 4 | 江崎 | 1 |
| 5 | 奥本 | 2 | 5 | 奥本 | 2 |
+----+------+------+----+------+------+
そうすると、結果にtypeがNULLのデータは含まれていません。
typeがNULLのデータも含んで欲しい場合は次のようにします。
SELECT * FROM sampleA
-> INNER JOIN sampleB
-> ON sampleA.name = sampleB.name
-> AND (sampleA.type = sampleB.type OR (sampleA.type IS NULL AND sampleB.type IS NULL));
+----+------+------+----+------+------+
| id | name | type | id | name | type |
+----+------+------+----+------+------+
| 1 | 赤井 | 1 | 1 | 赤井 | 1 |
| 2 | 井田 | 2 | 2 | 井田 | 2 |
| 3 | 宇野 | NULL | 3 | 宇野 | NULL |
| 4 | 江崎 | 1 | 4 | 江崎 | 1 |
| 5 | 奥本 | 2 | 5 | 奥本 | 2 |
+----+------+------+----+------+------+
NULLのデータも表示されました。
これをNULL安全等価演算子(宇宙船演算子)を使って抽出してみます。
SELECT * FROM sampleA
-> INNER JOIN sampleB
-> ON sampleA.name = sampleB.name
-> AND sampleA.type <=> sampleB.type;
+----+------+------+----+------+------+
| id | name | type | id | name | type |
+----+------+------+----+------+------+
| 1 | 赤井 | 1 | 1 | 赤井 | 1 |
| 2 | 井田 | 2 | 2 | 井田 | 2 |
| 3 | 宇野 | NULL | 3 | 宇野 | NULL |
| 4 | 江崎 | 1 | 4 | 江崎 | 1 |
| 5 | 奥本 | 2 | 5 | 奥本 | 2 |
+----+------+------+----+------+------+
いかがでしょうか。
SQL文が少しスッキリしていますよね。
皆さんにも是非活用していただければと思います。




