【実例付】PostgreSQLでNOT INを使う方法を丁寧に解説

※本サイトにはプロモーション・広告が含まれています。

(最終更新日:2023年6月)

✔このような方へ向けて書かれた記事となります

「PostgreSQLでNOT INを使いたいけど、どう書けばいいの?」
「PostgreSQLのNOT IN構文の使い方が知りたい」
「PostgreSQLのNOT INを活用した実例が見たい」

✔当記事を通じてお伝えすること

  • PostgreSQLでのNOT IN構文の基本
  • NOT IN構文の書き方やその応用
  • PostgreSQLでのNOT INを用いた実例

当記事では、PostgreSQLでのNOT IN構文の基本から、その使い方や応用例まで、具体的なケースを用いて詳しく解説しています。

ぜひ最後までお読みいただき、スキルアップに役立ててください。

筆者プロフィール

筆者プロフィールアイコン

【現職】プロダクトマネージャー

【副業】ブログ(月間20万PV)/YouTube/Web・アプリ制作

「プログラミング × ライティング × 営業」の経験を活かし、30後半からのIT系職へシフト。現在はプロダクトマネージャーとして、さまざまな関係者の間に入り奮闘してます。当サイトでは、実際に手を動かせるWebアプリの開発を通じて、プログラミングはもちろん、IT職に必要な情報を提供していきます。

【当ブログで紹介しているサイト】

当サイトチュートリアルで作成したデモ版日報アプリ

Django × Reactで開発したツール系Webアプリ

✔人に見せても恥ずかしくないコードを書こう

「リーダブルコード」は、わかりやすく良いコードの定義を教えてくれる本です。

  • 見るからにきれいなコードの書き方
  • コードの分割方法
  • 変数や関数の命名規則

エンジニアのスタンダートとすべき基準を一から解説しています。

何回も読むのに値する本なので、ぜひ手にとって読んでみてください。

NOT INとは

こちらでは、PostgreSQLのNOT INについて詳しく解説します。

まずは基本を理解しましょう。

  • PostgreSQLのNOT INの機能と目的
  • クエリの基本構文

PostgreSQLのNOT INの機能と目的

PostgreSQLのNOT INは、特定の値がリストに存在しないレコードを選択するためのSQL演算子です。

特定の条件に一致しないレコードを見つけ出す際に便利なツールとなります。

基本構文はWHEREの中で使います。

WHERE カラム名 NOT IN (値1,値2, …);

SQLのWHERE文については詳しくこちらに記載しています。

クエリの基本構文

NOT INの基本的な使用法は次の通りです。

SELECT column_name 
FROM table_name 
WHERE column_name NOT IN (value1, value2, …);

ここで、value1, value2, …は検索条件に一致しない値のリストです。

わかりやすいNOT INの使用例

このセクションでは、NOT INの具体的な使用例をいくつか紹介します。

具体例を見れば、すぐに使いこなせるはず。

  • ステータスが非表示のレコードを取得
  • サブクエリを使った条件に一致しないレコードの取得
  • 複数条件の利用: 複数のキーワードやIDに一致しないデータ抽出

ステータスが非表示のレコードを取得

ある商品データベースから「非表示」ステータスを除いたレコードを取得したい場合の例です。

SELECT * FROM products WHERE status NOT IN ('非表示');

ステータスが「非表示」でないすべての商品レコードが選択されます。

サブクエリを使った条件に一致しないレコードの取得

サブクエリを利用すると、ほかのテーブルやクエリの結果に基づいてデータをフィルタリングできます。

以下は、注文が未だに行われていない商品を検索する方法です。

SELECT * FROM products WHERE product_id NOT IN (SELECT product_id FROM orders);

ordersテーブルに存在しないproduct_idを持つproductsテーブルのレコードすべてが選択されます。

サブクエリについてはこちらをどうぞ。

複数条件の利用: 複数のキーワードやIDに一致しないデータ抽出

NOT INは、複数の条件を組み合わせて使用することも可能です。

たとえば特定のカテゴリに属さない商品を検索する場合、次のようなクエリを書けます。

SELECT * FROM products WHERE category_id NOT IN (1, 2, 3);

category_idが1, 2, 3のいずれでもないすべての商品レコードが選択されます。

NULL値への対処法

NOT IN操作とNULL値の相互作用について、詳しく見ていきましょう。

NULLがNOT INにどのように影響するかを解説し、その対処法を示します。

  • NULLが含まれるとどうなるか
  • NULL値を扱う実例

NULLが含まれるとどうなるか

NOT INのクエリを利用する際、注意すべきこととして、NULL値の扱いが挙げられます。

サブクエリがNULLを含む場合、NOT INはNULL値が含まれている行を除外するからです。

サブクエリがひとつでもNULLを返すと、NOT INを使用したメインクエリは何も返さなくなります。

-- メインクエリ
SELECT * FROM users
WHERE user_id NOT IN (
    -- サブクエリ
    SELECT user_id FROM orders WHERE status = 'completed'
);

-- サブクエリがNULLを返す場合 = ordersテーブルにcompletedステータスの行が存在しない場合
-- メインクエリは何も返さない

NULL値を扱う実例

考えられる解決策は、サブクエリ内でNULL値を明示的に除外することです。

例えば以下のようになります。

SELECT column_name 
FROM table_name 
WHERE column_name NOT IN (
  SELECT column_name 
  FROM table_name 
  WHERE condition IS NOT NULL
);

サブクエリ内でNULLを明示的に除外することで、メインクエリが結果を返すことが保証されます。

NOT INの効率に関する疑問とその解決

NOT INの効率について解説し、より効率的な代替手法を紹介します。

パフォーマンスでより良い選択ができる場合があるのです。

  • NOT INは遅い? 効率について考察
  • より効率的な代替手法の紹介:EXISTS, LEFT JOIN

NOT INは遅い? 効率について考察

SQLクエリのパフォーマンスにおいて、一部の状況では、NOT INは最も効率的な選択肢ではないことがあります。

なぜならNOT INは、サブクエリの結果を一時テーブルとして保持したうえで、それをメインクエリでフィルタリングに使用するからです。

サブクエリが大量の結果を返すと、一時テーブルが大きくなり、メインクエリのパフォーマンスが低下する可能性があります。

より効率的な代替手法の紹介:EXISTS, LEFT JOIN

パフォーマンスの問題に対処するためのひとつの方法は、NOT INの代わりにEXISTSやLEFT JOINを使用することです。

EXISTSは、サブクエリが一つでも結果を返せば真となり、それ以外の場合は偽となるため、大量のデータを扱う場合に有用です。

またLEFT JOINを使用すると、主テーブルの全てのレコードと結合テーブルの一致するレコードが返されます。

結合テーブルに一致するレコードがない場合、主テーブルの行はNULL値と共に返されるのです。

この性質を利用して、一致しない行の抽出も可能です。

関連機能の比較

ここでは、NOT INと同じくデータの選択に使うほかのSQL演算子について解説します。

具体的には、IN、ANY/SOME、およびALLについて見ていきましょう。

  • INの使い方(スカラ形式とサブクエリ形式)
  • ANY/SOMEとALLの使い方

INの使い方(スカラ形式とサブクエリ形式)

IN演算子は、指定した値のリストに値が存在する場合に真となる条件を作成します。

NOT INとは逆の動作をおこなうものです。

スカラ形式では、直接値のリストを指定します。

WHERE column IN (1,2,3)

サブクエリ形式では、サブクエリの結果をリストとして使用します。

WHERE column IN (SELECT column FROM table2)

table2のcolumnの値に一致する行が選択されるのです。

ANY/SOMEとALLの使い方

ANY(SOMEはANYと同じ意味)とALLも、サブクエリと共に使用され、特定の列の値が結果とどのように関連しているかをテストするものです。

ANYは、比較演算子と組み合わせて使用され、サブクエリのいずれかの結果と比較演算子が真になる場合に真が返されます。

WHERE column > ANY (SELECT column FROM table2)

columnの値がtable2のcolumnのいずれかの値より大きい行が選択されるものです。

一方ALLは、サブクエリのすべての結果と比較演算子が真のときに、真を返すもの。

WHERE column > ALL (SELECT column FROM table2)

columnの値がtable2のcolumnのすべての値より大きい行のみが選択されます。

PostgreSQLの応用した使い方・実例

PostgreSQLの応用した使い方をご覧いただきます。

  • PostgreSQLのNOT INについての概要と使用例
  • NULL値への対処法
  • 効率的なコード記述方法
  • その他のSQL機能との比較

PostgreSQLのNOT INについての概要と使用例

NOT INは、あるリストに存在しない値を持つ行を選択する際に使用するSQLのキーワードです。

サブクエリと組み合わせて、特定の列の値が他のテーブルの特定の列の値に一致しない行を選択するためにも使えます。

-- productsテーブルから特定のカテゴリに属さない商品を選択するクエリ

SELECT *
FROM products
WHERE category_id NOT IN (
    SELECT category_id
    FROM categories
    WHERE category_name = 'Electronics'
);

NULL値への対処法

NULL値が存在する場合、NOT INが期待通りの結果を返さないことは前述のとおり。

IS NOT NULLを使用してNULLを明示的に除外しましょう。

-- productsテーブルからカテゴリが'Electronics'でなく、かつcategory_idがNULLでない商品を選択するクエリ

SELECT *
FROM products
WHERE category_id NOT IN (
    SELECT category_id
    FROM categories
    WHERE category_name = 'Electronics'
) AND category_id IS NOT NULL;

効率的なコード記述方法

NOT INのパフォーマンスは、大きなデータセットでは問題になる可能性があります。

その場合はより効率的な代替手段として、EXISTSやLEFT JOINを使いましょう。

EXISTSを使う例

-- productsテーブルからカテゴリが'Electronics'でなく、かつcategory_idがNULLでない商品を選択するクエリ

SELECT *
FROM products p
WHERE NOT EXISTS (
    SELECT 1
    FROM categories c
    WHERE c.category_id = p.category_id
    AND c.category_name = 'Electronics'
);

LEFT JOINを使う例

-- productsテーブルとcategoriesテーブルをLEFT JOINし、カテゴリが'Electronics'でなく、かつcategory_idがNULLでない商品を選択するクエリ

SELECT p.*
FROM products p
LEFT JOIN categories c ON p.category_id = c.category_id
WHERE c.category_id IS NULL OR c.category_name <> 'Electronics';

まとめ

当記事でお伝えしたことをまとめると以下のとおり。

  • NOT INは、特定の値が含まれないレコードを探すためのもの
  • サブクエリを活用し、他テーブルなどと連動して操作できる
  • 効率を考えると、EXISTSやJOINを使う方ができてしている場合もある

PostgreSQLにおいて、NOT INは知っておくと便利な機能のひとつです。

ただし他の句と組み合わせることで、より効果が期待できるため、 NOT INだけの知識では足りません。

当サイトでは、SQLをはじめとしたさまざまなプログラミング言語についての記事を載せています。

ぜひ検索を活用し、プログラミング学習に役立ててください。

タイトルとURLをコピーしました