MySQLのNULL値の扱い方について(Vol2)

MySQL 8.0

はじめに

以下公式リファレンスには、NULL値について大きく分けてポイントが4点記載されておりますが、公式リファレンスを見ただけではNULL値の扱い方を十分に理解したとはなかなか言えないと思います。

NULL値の取り扱いを誤ると、SQLが期待通りに動作しないことがありますので、
前回の記事に引き続き、NULL値の扱い方について、いくつか検証してみましたので紹介したいと思います。

https://dev.mysql.com/doc/refman/8.0/ja/null-values.html

NULL値は「データなし」を意味します。 NULL は大文字と小文字のどちらでも記述できます。

NULL値は、数値型での 0 や文字列型での空文字列などの値とは異なります。

LOAD DATA または SELECT … INTO OUTFILE で実行されるテキストファイルのインポートまたはエクスポート操作の場合、NULL は\N 順序で表されます。

ORDER BY でソートする場合、NULL値は、昇順ソートの場合は他の値の前にソートされ、降順ソートの場合は他の値の後にソートされます。

目次

データ準備

本検証は、MySQL 8.0.26およびMySQL8.4.4で検証して問題ありませんでしたので、
MySQL8.0および8.4の仕様に差異はないと思います。
今回は検証用に1つのテーブルを作成し、テストデータを投入します。

テーブル構成としては、星座占いのデータとして、
「番号」、「星座(英語)」、「星座(日本語)」、「占い」を保持しています。

占いの結果を信じる/信じない、良い部分だけ信じる・・・
人それぞれ様々な意見があると思いますが、本ブログの内容は信じて頂けると幸いです!

ORDER BY によるNULL値を含めた値のソート方法

まずは、データをauto_numberで昇順/降順ソートしたときの挙動を見てみましょう。
公式リファレンスに記載されている通り、昇順ソートの場合は先頭にNULL値が表示され、
降順ソートの場合は末尾にNULL値が表示されます。

では、昇順ソートの場合はNULL値を末尾に表示したいと思います。
まずソートする際に必要なことは、ORDER BY句の記載を以下のようにすることです。

第1ソート:「ソートしたいカラム IS NULL」
第2ソート:「ソートしたいカラム」

具体的なSELECT文と結果は以下のようになりますが、
SELECT句の先頭2列にソートキーの値を表示することで、
なぜNULL値が末尾に表示されるか、一目でわかると思います!

次に降順ソートの場合はNULL値を先頭に表示したいと思います。
こちらのORDER BY句の記載は以下のようになります。

第1ソート:「ソートしたいカラム IS NULL desc」
第2ソート:「ソートしたいカラム desc」

以下の結果を確認するとNULL値を先頭に表示できます!
結論としてNULL値を意識してソートする場合は、2つ指定する必要があります。

NULL値のレコードを正しくカウントする方法は?

ケース1:COUNT関数

まずは失敗例を見ていきましょう。
パッとSQLを見る限りはNULL値をカウントできそうな気配はありますが、
結果は0件です・・・。

前回の記事でも少し触れていますが、
COUNT関数とNULL値の関係性として、COUNT関数の引数にauto_numberを指定した場合は、
NULL値はカウントされませんので、0件になります。

NULL値のレコードを正しくカウントしたい場合は、
以下のように、count(*)を使うと表示できます!!

補足として、NULL値を含めて全レコードをカウントしたい場合も、count(*)を指定します。

どうしてもカラムを指定して全レコードをカウントしたい場合は、
IFNULL関数やCOALESCE関数、CASEを利用することで実現できますが・・・
以下のように「IS NULL」や「<=>」演算子を利用しても表示できます!

ケース2:SUM関数

ここまでの記事を読んで勘の良い方は、
どうすればNULL値のレコードを正しくカウントできるか見当がつくと思います。
ヒントは以下のSELECT文の結果を利用します・・・

以下のように「IS NULL」や「<=>」演算子 + 「SUM関数」を利用しても表示できます!

こちらもIFNULL関数やCOALESCE関数、CASEを利用することで実現できます。
例えばCASEを利用すると様々な条件式を記載でき、自由度も高いですが、
記述も長くなってしまいますので、ケースバイケースで使い分けする形も良いと思います。

IN句でNULL値を含めた検索はできる/できない

前回の記事で関係比較演算子や論理演算子を利用して、
NULL値が表示できるか検証しましたが、どんなに頑張っても表示できませんでした・・・

まずは、深く考えずに文法通りにSELECT文を記載してみましたが、
以下の結果を見ると再び「不可能」、「絶望」という文字が頭に浮かびます・・・。

IN句を利用してNULL値だけを抽出することができない状況で、
NULL値とそれ以外の値を表示することは可能なのか???

そして考えること10分~15分・・・
完成したSELECT文と結果は以下の通りです!!!

まずはNULL値のみを抽出する例です。
「auto_number IS NULL」と「1」の組み合わせを使うことで抽出できます!

さらに、IN句内でカンマ区切りを利用して、
NULL値とNULL値以外の値を抽出することも可能です。

そしてIN句をネストすることで、
NULL値+複数の値を表示することができます!!

まさかのLIKEとNULL値のコラボは実現するのか・・・

IN句でNULL値を含めた検索ができるのであれば、
もしかしたらLIKEとNULL値のコラボも実現する方法があるのでは?

・・・そんな些細な疑問から
無謀とも思えるこのお題を検証してみました!

まずは一般的な文法に沿って、LIKEとNULL値を組み合わせてみると
以下のように表示される件数は0件です・・・。

結論としては、
LIKEとNULL値だけ組み合わせても、なかなか実現は難しいです・・・

しかし、LIKEとNULL値とIN句を組み合わせると、
もしかしたら出来るのではないかなと考え、検証をしてみました。

「いやいや、そもそもLIKEとIN句を同時に利用することは出来ないでしょう」
・・・そう思う方もいると思いますが、なんと同時に利用可能です!!

そして、以下のように記載することで、
少し無理やりですが、NULL値を含めたあいまい検索の完成です!!!

もう少しスッキリ記載すると以下の2パターンになります。
SELECT文だけに注目すると、2パターン目に記載しているIN句の左辺は「TRUE」と記載した方が表示できるイメージを持ちやすいかもしれません!

IN句やLIKEを利用してSELECT文は記載できたけど、インデックスは使えないのでは?
・・・そんな疑問が出てくると思いますが、それは次回以降記事にしたいと思います!!

まとめ

本ブログを記述するにあたり、
IN句やLIKEを利用してNULL値を含めたデータを抽出するというのは、
さっとWEBで調べたところ、ストライクな情報が記載されているページは見当たりませんでした。。。

本ブログ執筆前は、それほどNULL値の検証に苦戦するとは考えていなかった一方、
ある程度求めていた結果が得られたときは「やればできる」という言葉が浮かびました。

「やればベストを尽くすことができる。挑戦こそ楽しいことである。」

・・・という意味が込められた
この言葉の通り、挑戦してベストを尽くすことができたと思いますので、
今回、紹介した内容が皆様のご参考にもなればより幸いです!!

次回は、「Left JoinとNULL値の関連性」や「NULL値とインデックスの関連性」などについて紹介したいと考えています!

スマートスタイルTECHブログについて

スマートスタイルTECHブログでは、日頃MySQLのサポート業務に従事している有資格者で構成された技術サポートチームがMySQLに関する技術情報を発信しています。データベースのお困りごとはお気軽にご相談下さい。

よかったらシェアしてね!
  • URLをコピーしました!
目次