不等価演算子は <> または != と書き、2つの値が異なるときに真になります。WHERE 句で使うと、特定の値に一致する行を除外できます。サンプルは PostgreSQL、MySQL、SQLite、SQL Server で動作します。
不等価演算子の使い方
2つの値の間に <> または != を置きます。どちらもまったく同じ意味です。<> は SQL 標準の表記で、!= は多くのプログラミング言語で使われる表記です。
value1 <> value2
value1 != value2
SELECT 5 <> 3;
-- Output: true
SELECT 'apple' != 'apple';
-- Output: false
SELECT NULL <> 3;
-- Output: NULL
-- MySQL and SQLite show true and false as 1 and 0. SQL Server can't
-- select a comparison like this: use it in a WHERE clause there.
クエリでは、不等価演算子を WHERE 句に書くと、値が異なるすべての行が残ります:
-- Input: tickets
-- id | subject | status
-- ---+-----------------------+--------
-- 1 | Login fails on Safari | open
-- 2 | Typo on pricing page | closed
-- 3 | Export times out | pending
-- 4 | Add a dark theme | NULL
SELECT id, subject, status
FROM tickets
WHERE status <> 'closed';
-- Output:
-- id | subject | status
-- ---+-----------------------+--------
-- 1 | Login fails on Safari | open
-- 3 | Export times out | pending
チケット4のステータスは 'closed' ではないのに、結果に含まれていません。これが次に説明する1つ目のルールです。
知っておくべきルール
-
不等価演算子は NULL に一致しません。NULL と何かを比較すると、真ではなく NULL(不明)になるため、
WHERE句でその行は除外されます。値のない行も残すにはOR column IS NULLを追加します:
-- Input: the tickets table above
SELECT id, subject, status
FROM tickets
WHERE status <> 'closed' OR status IS NULL;
-- Output:
-- id | subject | status
-- ---+-----------------------+--------
-- 1 | Login fails on Safari | open
-- 3 | Export times out | pending
-- 4 | Add a dark theme | NULL
-
NOT INのリストに NULL があると、すべての行が除外されます。status NOT IN ('closed', 'pending')はstatus <> 'closed' AND status <> 'pending'の省略形なので、リストに NULL が1つでもあると条件全体が不明になります。NULL を許可する列に対するサブクエリからリストを作る場合は注意してください:
-- Input: the tickets table above
SELECT id, status FROM tickets WHERE status NOT IN ('closed', 'pending');
-- Output:
-- id | status
-- ---+-------
-- 1 | open
SELECT id, status FROM tickets WHERE status NOT IN ('closed', NULL);
-- Output:
-- id | status
-- ---+-------
-- (0 rows)
-
MySQL と SQL Server はデフォルトで大文字と小文字を区別しないため、これらでは
'Apple' <> 'apple'は偽になります。 -
可能なら、欲しいものを直接指定しましょう。
status <> 'closed'は後から追加されたステータスにも一致します。また、通常はテーブルの大部分に一致するため、インデックスがほとんど役に立ちません。「open または pending」という意味なら、status IN ('open', 'pending')と書けばそのとおりに伝わります。
別の書き方
NOT (status = 'closed') は status <> 'closed' の別の書き方で、同じように NULL を除外します。
NULL による思わぬ結果を避けて比較するには、IS DISTINCT FROM を使います。これは NULL を1つの値として扱う NULL セーフな不等価比較です(SQL Server は 2022、SQLite は 3.39 で対応):
-- Input: the tickets table above
SELECT id, status FROM tickets WHERE status IS DISTINCT FROM 'closed';
-- Output:
-- id | status
-- ---+--------
-- 1 | open
-- 3 | pending
-- 4 | NULL
-- MySQL has no IS DISTINCT FROM. Use its NULL-safe <=> instead:
SELECT id, status FROM tickets WHERE NOT (status <=> 'closed');
不等価演算子はいつ使うべき?
特定の値を持つ行をクエリから除外したいときに使います。ほとんどの用途は次の5つのいずれかに当てはまります。
特定のステータスやカテゴリを除外する
キャンセルされた注文、無効な請求書、取り扱っていないカテゴリなど、<> はその値を持つ行を除外し、それ以外をすべて残します。
特定のレコードを1件除外する
ID を比較して、特定の行やグループを除外します。関連記事を一覧表示するときに閲覧中の記事を除く、他のメンバー一覧からログイン中のユーザーを除く、全社レポートから特定の部署を除く、といった使い方です。数値に引用符は不要です。
他の条件と組み合わせて絞り込む
<> を AND や OR と組み合わせると、ある値を除外しつつ他の列で絞り込めます。たとえば、キャンセルされておらず、一定額を超える注文などです。同じ列の複数の値を除外するには NOT IN を使います。
2つの列の値が異なる行を探す
不等価演算子は列同士の比較にも使えます。古い値と新しい値、実際の数量と記録上の数値、配送先住所と請求先住所などを比較できます。
値がない行も残す
<> は NULL を除外するため、値のない行を結果に含めるかどうかを決めておきましょう。含める場合は OR column IS NULL を追加するか、前述の NULL セーフな構文を使います。
不等価演算子の実例
有効な請求書だけを合計する
無効な請求書は売上に含めるべきではありません:
-- Input: invoices
-- invoice_id | customer | status | amount
-- -----------+------------+--------+--------
-- 1001 | Acme Corp | paid | 1200.00
-- 1002 | Birch & Co | void | 450.00
-- 1003 | Acme Corp | open | 300.00
-- 1004 | Cobalt Ltd | paid | 875.50
SELECT SUM(amount) AS invoiced
FROM invoices
WHERE status <> 'void';
-- Output: 2375.50
閲覧中の記事を除いて関連記事を表示する
読者が記事2を閲覧中です。同じトピックの他の記事を表示します:
-- Input: articles
-- id | title | topic
-- ---+----------------------+-------
-- 1 | Indexing basics | SQL
-- 2 | Your first JOIN | SQL
-- 3 | Docker for beginners | DevOps
-- 4 | Window functions | SQL
SELECT id, title
FROM articles
WHERE topic = 'SQL'
AND id <> 2;
-- Output:
-- id | title
-- ---+-----------------
-- 1 | Indexing basics
-- 4 | Window functions
販売可能な商品だけを表示する
販売終了の商品、価格未設定の商品、在庫切れの商品を除外します:
-- Input: products
-- product_name | category | price | stock_quantity
-- ---------------+--------------+-------+---------------
-- Desk Organizer | Office | 18.50 | 40
-- Fax Machine | Discontinued | 89.00 | 3
-- Gift Wrap | Seasonal | 0.00 | 120
-- Trail Backpack | Outdoors | 64.00 | 0
-- Water Bottle | Outdoors | 12.99 | 75
SELECT product_name, category, price
FROM products
WHERE category <> 'Discontinued'
AND price > 0
AND stock_quantity <> 0;
-- Output:
-- product_name | category | price
-- ---------------+----------+------
-- Desk Organizer | Office | 18.50
-- Water Bottle | Outdoors | 12.99
実際に変更されたフィールドを探す
監査ログには、何も変更しなかった保存も含め、すべての保存が記録されます。2つの列を比較して、実際の変更だけを残します:
-- Input: audit_log
-- log_id | field_name | old_value | new_value
-- -------+------------+-------------+------------
-- 1 | email | dan@old.com | dan@new.com
-- 2 | city | Austin | Austin
-- 3 | plan | free | pro
SELECT log_id, field_name, old_value, new_value
FROM audit_log
WHERE old_value <> new_value;
-- Output:
-- log_id | field_name | old_value | new_value
-- -------+------------+-------------+------------
-- 1 | email | dan@old.com | dan@new.com
-- 3 | plan | free | pro
どちらかの列が NULL になりうる場合は、IS DISTINCT FROM(MySQL では NOT (old_value <=> new_value))を使ってください。そうしないと、初めて設定された値が変更としてカウントされません。
まだ「参加」と答えていない全員にリマインドする
返信していないゲストの rsvp は NULL で、彼らこそリマインダーが最も必要です:
-- Input: invitations
-- guest | email | rsvp
-- ------------+------------------+------
-- Ines Moreau | ines@example.com | yes
-- Raj Patel | raj@example.com | no
-- Hana Sato | hana@example.com | NULL
-- Leo Grant | leo@example.com | maybe
SELECT guest, email, rsvp
FROM invitations
WHERE rsvp <> 'yes' OR rsvp IS NULL;
-- Output:
-- guest | email | rsvp
-- ----------+------------------+------
-- Raj Patel | raj@example.com | no
-- Hana Sato | hana@example.com | NULL
-- Leo Grant | leo@example.com | maybe
不等価演算子についてさらに詳しく
このブログの関連記事:
- SQL COALESCE ガイド: 比較の前に NULL を値に置き換える
-
SQL LIKE ガイド:
NOT LIKEでパターンに一致するテキストを除外する - SQL CASE 文ガイド: 比較を使って値を選ぶ
- SQL の Having と Where の違い: 行をグループ化するときにフィルターをどこに書くか
- PostgreSQL で2つの値を比較する: その他の比較演算子
公式ドキュメント:
Beekeeper Studioは無料のオープンソースのデータベースGUIです
これまで使った中で最高のSQLクエリ&エディタツールです。データベースの管理に必要なものがすべて揃っています。 - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studioは高速で直感的、そして使いやすいツールです。多数のデータベースに対応し、Windows、Mac、Linuxで快適に動作します。
Beekeeper Studio 利用者の声
「Beekeeper Studio は以前の SQL ワークフローを完全に置き換えました。高速で直感的、データベース作業がまた楽しくなりました。」
「多くのデータベース GUI を試しましたが、Beekeeper は機能とシンプルさのバランスが絶妙です。とにかくちゃんと動きます。」