SQLには論理否定という言葉があります。
これはNOTの事を指しますが、この記事では特に演算子のNOTについて解説してみたいと思います。
NOT自体はそう難しいものではありませんので、SQLの学習を始めたばかりの方も覚えておきましょう。
論理否定とは
ITでいう論理否定とは論理演算の一つで、「与えられた命題が真のときに偽となり、偽の時に真となるもの」とされています。
もう少し噛み砕いて言うと、「クエリで指定した条件が逆になる」とも言えます。
この「論理否定」という用語はあまり馴染みのない用語のように聞こえますが、ビット演算では非常によく使われています。
ビット演算とはその名の通りビット(0か1)を操作するための演算ですが、NOT演算子を使うことで、「1であれば0、0であれば1にしてください」というような操作が可能です。
要はスイッチと同じ作用を作ることが出来るというわけです。
NOTの使い方
ではまず、NOT自体の簡単な使い方から解説していきたいと思います。
次のクエリを見てください。
SELECT * FROM sample_table WHERE id = '1';
比較的簡単なクエリですね。
このクエリを実行した際に期待される結果としては、「IDというカラムが”1″に該当するレコードを”sample_table”から取得する」というものです。
MariaDB [sample]> select * from stuffs; +----+--------+--------+ | id | sei | mei | +----+--------+--------+ | 1 | 山田 | 孝之 | | 2 | 岡本 | 忍 | | 3 | 内山 | 直哉 | | 4 | 実道 | 昇 | | 5 | 山之内 | みはる | | 6 | 合谷 | 新平 | | 7 | 春山 | 美奈 | | 8 | 三木谷 | 隆太 | | 9 | 道影 | 慎吾 | | 10 | 手塚 | はると | +----+--------+--------+ 10 rows in set (0.001 sec) MariaDB [sample]> select * from stuffs where id = '1'; +----+------+------+ | id | sei | mei | +----+------+------+ | 1 | 山田 | 孝之 | +----+------+------+ 1 row in set (0.000 sec)
実行すると期待通りの結果が確認できます。
それではこのクエリにNOTを使い「論理否定」で再構築してみます。
SELECT * FROM sample_table WHERE NOT id = '1';
NOTは論理否定なので、WHEREの後に付けることで「条件否定」の形になります。
MariaDB [sample]> select * from stuffs where not id = 1; +----+--------+--------+ | id | sei | mei | +----+--------+--------+ | 2 | 岡本 | 忍 | | 3 | 内山 | 直哉 | | 4 | 実道 | 昇 | | 5 | 山之内 | みはる | | 6 | 合谷 | 新平 | | 7 | 春山 | 美奈 | | 8 | 三木谷 | 隆太 | | 9 | 道影 | 慎吾 | | 10 | 手塚 | はると | +----+--------+--------+ 9 rows in set (0.000 sec)
実行結果を見ると、「id = 1」以外が取得されていることが確認できます。
NOTの優先順位
演算子にはそれぞれ優先順位というものが存在します。
この優先順位は、レベルという概念が存在し、このレベルが高いほどクエリ中で先に評価(実行)される仕組みとなっています。
ただし難しく考える必要は全くなく、暗記出来るほど簡単なものとなっています。
上から順にレベルの高いものとなっています。
- 単項 + – 算術演算子、PRIOR演算子
- * / 算術演算子
- バイナリ + – 算術演算子、|| 文字演算子
- すべての比較演算子( =、>、<、>=、<=、<>、!=、!>、!< )
- NOT論理演算子
- AND論理演算子
- OR論理演算子
この中で覚えておくべきは「全ての論理演算子(AND, OR, NOT)は全ての比較演算子よりレベルが低い」という部分です。
NULLに注意
NOT演算子を使って検索をかける際には若干の注意が必要な場合があります。
それはレコードに「null」がある場合です。
nullがある場合にはnullは検索対象外となってしまうため、期待した結果を得られない場合があります。
早速サンプルコードで見てみましょう。
MariaDB [sample]> SELECT * FROM sample_table; +----+------------+-----------+------------+--------+ | id | first_name | last_name | birth | gender | +----+------------+-----------+------------+--------+ | 1 | noah | smith | 1980-04-21 | male | | 2 | ava | brown | 1986-06-15 | female | | 3 | mia | williams | 1976-05-11 | female | | 4 | lucas | taylor | 1990-12-01 | male | | 5 | jackson | jones | 1988-07-24 | male | | 6 | logan | wilson | 1991-01-17 | NULL | | 7 | sofia | thomas | 1977-08-22 | female | | 8 | chloe | martin | 1995-11-13 | NULL | | 9 | stella | white | 1982-03-03 | female | | 10 | amelia | harris | 1985-04-16 | female | +----+------------+-----------+------------+--------+ 10 rows in set (0.000 sec)
データベースに上のようなサンプルテーブルを用意しましたが、idが”6″と”8″に該当するレコードはgenderをnullに設定してあります。
では先ほど解説したNOT演算子を使い、「性別が男性以外」の全てのレコードを取得してみましょう。
通常であれば記述は次のように予想できます。
SELECT * FROM sample_table WHERE gender != 'male';
しかし実際にこのクエリを実行してみると以下のようになります。
MariaDB [sample]> SELECT * FROM sample_table WHERE gender != 'male'; +----+------------+-----------+------------+--------+ | id | first_name | last_name | birth | gender | +----+------------+-----------+------------+--------+ | 2 | ava | brown | 1986-06-15 | female | | 3 | mia | williams | 1976-05-11 | female | | 7 | sofia | thomas | 1977-08-22 | female | | 9 | stella | white | 1982-03-03 | female | | 10 | amelia | harris | 1985-04-16 | female | +----+------------+-----------+------------+--------+ 5 rows in set (0.000 sec)
実行結果ではnullも一緒に除外されていることが確認できます。
これはnullというものが比較対象としては除外されるためで、このnullを取得する際には更に別の方法を併用する必要があります。
方法は以下の通りです。
MariaDB [laravel]> SELECT * FROM sample_table -> WHERE -> gender != 'male' -> OR -> gender IS NULL; +----+------------+-----------+------------+--------+ | id | first_name | last_name | birth | gender | +----+------------+-----------+------------+--------+ | 2 | ava | brown | 1986-06-15 | female | | 3 | mia | williams | 1976-05-11 | female | | 6 | logan | wilson | 1991-01-17 | NULL | | 7 | sofia | thomas | 1977-08-22 | female | | 8 | chloe | martin | 1995-11-13 | NULL | | 9 | stella | white | 1982-03-03 | female | | 10 | amelia | harris | 1985-04-16 | female | +----+------------+-----------+------------+--------+ 7 rows in set (0.000 sec)
まとめ
いかがでしたか?今回はNOT演算子について優先順位や注意点などを中心に解説してみましたが、ご理解いただけたでしょうか?
NOT自体は比較演算子の「!=」に置き換えて使用することが多いですが、理論演算子というものもあるということだけでも覚えておいてください。