カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

MySQLのNULL安全等価演算子(宇宙船演算子)

この記事は最終更新日から1年以上経過しています。

今回はMySQLでのNULL安全等価演算子についてご紹介します。
NULL安全等価演算子とは<=>のことで、見た目が宇宙船に似ていることからSpaceship Operator(宇宙船演算子)とも言われます。
※他言語でもあるんですが、返り値が違ったりするのでご注意ください。

まず、値の比較について見ていきます。

11を等価演算子で比較します。

MySQL> SELECT 1 = 1;
+-------+
| 1 = 1 |
+-------+
|     1 |
+-------+

結果は真の1となりました。

次は10を比較してみましょう。

MySQL> SELECT 1 = 0;
+-------+
| 1 = 0 |
+-------+
|     0 |
+-------+

結果は偽の0となりました。

今後は1NULLを比較してみます。

MySQL> SELECT 1 = NULL;
+----------+
| 1 = NULL |
+----------+
|     NULL |
+----------+

結果は偽の0となるかと思いきや、NULLとなりました。

NULL同士を比較するとどうでしょうか。

MySQL> SELECT NULL = NULL;
+-------------+
| NULL = NULL |
+-------------+
|        NULL |
+-------------+

結果はNULLとなりました。

1NULLの場合は0NULL同士の場合は1になって欲しいですよね。
そこで登場するのが、今回のNULL安全等価演算子(宇宙船演算子)です。
それを使うと次のようになります。

1NULLの場合

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    |
+----+--------+------+

sampleAsampleBは全く同じ内容です。

ここで、sampleAsampleBnametypeを結び付けてデータを抽出してみます。

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 |
+----+------+------+----+------+------+

そうすると、結果にtypeNULLのデータは含まれていません。
typeNULLのデータも含んで欲しい場合は次のようにします。

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文が少しスッキリしていますよね。
皆さんにも是非活用していただければと思います。

この記事がお役に立ちましたらシェアお願いします
2,178 views

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です