【SQL】NOT INの使い方!基本からよくある問題まで!

みなさんこんにちは!

フリーランスプログラマーのsatoです。

今回はIN句の否定型、「NOT IN句」について見ていきましょう!

  • [基本]「NOT IN」とは
  • [基本]「NOT IN」の使い方
  • [応用]NULLが含まれると…?
  • [応用]「NOT IN」は遅いの?

前半で基本的な使い方も見つつ、よく質問として上がるNULLだとどうなるのかや、処理速度について後半で追求したいと思います。

ぜひ、一通り学んで見てください。こういう細かい点を把握しておくことも、一歩上を目指す時に重要になるところですね!

目次

「NOT IN」とは

先ほども言った通りIN句の否定型が「NOT IN句」です。一言でその機能を説明するなら「指定した要素を含んでいないレコード(行)を取得する」と言ったところでしょうか。

おおもとの「IN句」の詳細は以下のリンクにまとめてあります。「NOT IN句」を知りたいのならば、まずこちらを読むことが理解を含める最短距離でしょう。

ぜひ読んでみてください。

「NOT IN」の使い方

では早速使い方に入っていきましょう。

例えばfruit(ブルーツ)テーブルがあったとします。その中で、「みかん・りんご」ではないレコード(行)を取得したいなら以下の通りに書きましょう。

SELECT * FROM fruit WHERE name NOT IN("みかん","りんご");

INの前にNOTをつけるだけです。簡単ですね!

サブクエリを扱うには

サブクリエとは、「SELECT文で取得したデータを用いて、SELECT文(やUPDATE文など)を使用する技術」です。非常に有用な技術なので、ぜひともマスターしておきましょう。

「NOT IN句」では以下のように書くことでそれを実現可能です。

SELECT * FROM [テーブルA]
WHERE
  [要素名] NOT IN (
      SELECT [要素名] FROM [テーブルB]
    );

詳細はIN句の説明にまとめてありますので、気になる人はぜひ読んでおいてください。

NULLが含まれると…?

実は「NOT IN句」の判定の中にnullが一つでも含まれていると、何も取得できない状況におちいってしまいます。

実例

例えば以下のようテーブルで、以下の処理を実行したとしましょう。

テーブル:

+------+-----------+
| id   | name      |
+------+-----------+
|    1 | りんご    |
|    2 | みかん    |
|    3 | ばなな    |
+------+-----------+

実行命令:

SELECT * FROM fruit WHERE NAME NOT IN("みかん","りんご",null);

りんごやみかんでない「ばなな」が取得できそうな気がしますが、結果は何も取得できません。いくら、みかん・りんごに一致する内容があったとしても、nullがあるせいで、何も取得できないのです。

これには、根の深い原因があるのですが…この記事は初心者向けということで、細かい原因はの説明は、別の機会に回しましょう。「NOT IN句」にnullを入れると、何も取得できなくなる。そのことを覚えておいてください。

「NOT IN」は遅いの?

他のサイトでも、色々と遅い原因の話が挙げられますが、個人的には、正直一概には言えないと考えています。それは環境や、データベースの構成にもよるからです。

とはいえ基本的に否定形の処理はインデックスが効かないケースが多々あります。インデックスが効かない状況ではデータ量が増えると急激に遅くなりますので、「NOT IN」が、処理速度のネックになる可能性は大いにありえるでしょう。

もし大規模なデータベースを扱う場合は、そもそも検索範囲の広い否定形処理は使用しない設計にすることをおすすめします。

まとめ

今回は「IN句」の否定形「NOT IN句」について見てきました。

  • NULLの問題に気をつけること
  • 処理速度に気をつけること

これら2点に気をつければ非常にシンプルで有用な命令です。上手に使っていきましょう!

この記事を書いた人

学生時代を含めると、かれこれ10年以上プログラマーとして過ごしています。
様々な言語や環境、プロジェクトに関わってきましたので、より実践的な記事をみなさんにお届きるよう情報発信していきます!

目次