PostgreSQL WHERE句
WHERE句はSQLにおけるデータフィルタリングの基礎です。これを使用することで条件を指定し、SELECT、UPDATE、またはDELETEステートメントの結果セットに含まれる行を決定できます。WHERE句がない場合、これらのステートメントはテーブル内のすべての行に影響を与えますが、これは通常望ましい結果ではありません。
WHERE句をマスターすることは、PostgreSQLデータベースから価値のある情報を抽出し、特定のデータを操作するための鍵となります。本章では、WHERE句を効率的に使用するための詳細を深く掘り下げ、データを正確に特定・管理する能力を身につけていただきます。
1. WHERE句の理解
SQLにおける WHERE 句はレコードをフィルタリングするために使用されます。これを使用して、レコードが結果セットに含まれるために満たすべき条件を指定します。SELECT、UPDATE、DELETEステートメントの不可欠な要素であり、データの特定のサブセットを処理することを可能にします。
1.1 基本構文
WHERE句を伴う SELECT ステートメントの基本構文は以下の通りです。
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE 条件;ここでの 条件(condition) は、評価結果が true(真)、false(偽)、または unknown(未知/NULL)となるブール式です。条件の評価結果が true の場合のみ、対応する行が結果セットに含まれます。
2. 比較演算子
比較演算子は、WHERE句で異なる値を比較するために使用されます。以下は頻繁に使用される演算子のまとめです。
=: 等しい<>または!=: 等しくない>: より大きい<: より小さい>=: 以上<=: 以下
例:
次のような customers(顧客)テーブルがあると仮定します。カラムには customer_id(顧客ID)、name(姓名)、city(都市)、order_total(注文総額)などが含まれます。
ニューヨークの顧客を検索する:
SELECT customer_id, name
FROM customers
WHERE city = 'New York';このクエリは、ニューヨーク(New York)に居住しているすべての顧客の customer_id と name を抽出します。
注文総額が 100 を超える顧客を検索する:
SELECT customer_id, name, order_total
FROM customers
WHERE order_total > 100;このクエリは、order_total が 100 より大きいすべての顧客の customer_id、name、および order_total を抽出します。
注文総額が 50 ではない顧客を検索する:
SELECT customer_id, name, order_total
FROM customers
WHERE order_total <> 50;このクエリは、order_total が 50 ではないすべての顧客の詳細情報を抽出します。
3. 論理演算子
論理演算子は、WHERE句で複数の条件を組み合わせるために使用されます。主な論理演算子は以下の通りです。
- AND : 両方の条件が真の場合に真を返します。
- OR : いずれかの条件が真の場合に真を返します。
- NOT : 条件を反転させます。
例:
ニューヨーク出身で、かつ注文総額が 100 を超える顧客を検索する:
SELECT customer_id, name, city, order_total
FROM customers
WHERE city = 'New York' AND order_total > 100;このクエリは、ニューヨーク出身であり、かつ 100 を超える注文総額を持つ顧客を返します。
ニューヨークまたはロサンゼルスの顧客を検索する:
SELECT customer_id, name, city
FROM customers
WHERE city = 'New York' OR city = 'Los Angeles';このクエリは、ニューヨークまたはロサンゼルス出身の顧客を返します。
シカゴ出身ではない顧客を検索する:
SELECT customer_id, name, city
FROM customers
WHERE NOT city = 'Chicago';このクエリは、シカゴ出身ではない顧客を返します。これは WHERE city <> 'Chicago' を使用するのと同等です。
4. UPDATE と DELETE における WHERE の利用
WHERE句は UPDATE および DELETE ステートメントにおいても極めて重要です。
- UPDATE : 条件に基づいて特定の行を修正します。
- DELETE : 条件に基づいて特定の行を削除します。
例:
IDが 123 の顧客の注文総額を更新する:
UPDATE customers
SET order_total = 150
WHERE customer_id = 123;このステートメントは、customer_id が 123 の顧客の order_total を 150 に更新します。
IDが 456 の顧客を削除する:
DELETE FROM customers
WHERE customer_id = 456;このステートメントは、customer_id が 456 の顧客を削除します。DELETEステートメントを使用する際は細心の注意を払ってください。(WHERE条件を指定しない場合、テーブル全体が空になります!)
5. 高度な WHERE 句の条件
基本的な比較演算子や論理演算子に加え、WHERE句はより複雑な条件をサポートしており、強力なフィルタリング機能を実現するための追加の演算子や関数を利用できます。
5.1 BETWEEN 演算子
BETWEEN 演算子は、指定された範囲内の値を選択するために使用されます。これは境界値を含む(inclusive)ため、開始値と終了値も結果に含まれます。
構文:
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE カラム名 BETWEEN 値1 AND 値2;例:
orders(注文)テーブルから、2023年1月1日から2023年1月31日の間に注文されたすべてのレコードを取得する場合(order_date カラムを使用):
SELECT order_id, customer_id, order_date
FROM orders
WHERE order_date BETWEEN '2023-01-01' AND '2023-01-31';このクエリは、2023年1月のすべての注文を返します。
5.2 LIKE 演算子
LIKE 演算子はパターンマッチングに使用されます。通常、以下のワイルドカードと共に使用されます。
%: 0文字、1文字、または複数文字を表します。_: 単一の文字を表します。
構文:
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE カラム名 LIKE パターン;例:
名前が 'A' で始まる顧客:
SELECT customer_id, name
FROM customers
WHERE name LIKE 'A%';このクエリは、名前がアルファベットの 'A' で始まるすべての顧客を返します。
名前に 'an' が含まれる顧客:
SELECT customer_id, name
FROM customers
WHERE name LIKE '%an%';このクエリは、名前に文字列 'an' を含むすべての顧客を返します。
名前の2文字目が 'a' の顧客:
SELECT customer_id, name
FROM customers
WHERE name LIKE '_a%';このクエリは、名前の2文字目が 'a' であるすべての顧客を返します。
5.3 IN 演算子
IN 演算子を使用すると、WHERE句で複数の値を指定できます。ある値がリスト内のいずれかの値と一致するかどうかをチェックします。
構文:
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE カラム名 IN (値1, 値2, ...);例:
ニューヨーク、ロサンゼルス、またはシカゴ出身の顧客を検索する:
SELECT customer_id, name, city
FROM customers
WHERE city IN ('New York', 'Los Angeles', 'Chicago');これは以下の書き方と同等です。
SELECT customer_id, name, city
FROM customers
WHERE city = 'New York' OR city = 'Los Angeles' OR city = 'Chicago';しかし、特に値のリストが長い場合、IN を使用したほうが簡潔であり、通常は効率も高くなります。
5.4 IS NULL および IS NOT NULL 演算子
これら2つの演算子は NULL(空の値)をチェックするために使用されます。NULLとの比較に = や <> を使用することはできません。
構文:
-- NULLを検索
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE カラム名 IS NULL;
-- NULL以外を検索
SELECT カラム1, カラム2, ...
FROM テーブル名
WHERE カラム名 IS NOT NULL;例:
customers テーブルに、NULLになる可能性がある phone(電話)カラムがあると仮定します。
電話番号が登録されていない顧客:
SELECT customer_id, name
FROM customers
WHERE phone IS NULL;このクエリは、phone カラムが NULL であるすべての顧客を返します。
電話番号が登録されている顧客:
SELECT customer_id, name
FROM customers
WHERE phone IS NOT NULL;このクエリは、phone カラムが NULL ではないすべての顧客を返します。
6. 条件の組み合わせ
論理演算子(AND、OR、NOT)を使用して複数の条件を組み合わせ、複雑なフィルタリング基準を作成できます。演算子の優先順位に注意し、括弧を使用して計算の順序を明確に定義することが不可欠です。
例:
「ニューヨーク出身で注文総額が 100 を超える」か、または「ロサンゼルス出身」のいずれかに該当する顧客を検索する:
SELECT customer_id, name, city, order_total
FROM customers
WHERE (city = 'New York' AND order_total > 100) OR city = 'Los Angeles';括弧を使用することで、AND 条件が OR 条件よりも先に計算されることを保証します。もし括弧がない場合、クエリは次のように解釈されます。
SELECT customer_id, name, city, order_total
FROM customers
WHERE city = 'New York' AND (order_total > 100 OR city = 'Los Angeles');これは全く異なる結果を返します。ニューヨーク出身のすべての顧客が無条件に含まれ(注文総額に関わらず)、かつロサンゼルス出身の顧客も含まれることになります。
7. 大文字小文字の区別
デフォルトでは、PostgreSQLの文字列比較は 大文字と小文字を区別(Case-sensitive) します。つまり 'New York' と 'new york' は別のものとして扱われます。
例:
SELECT customer_id, name, city
FROM customers
WHERE city = 'new york'; -- データベースに 'New York' と保存されている場合、結果は空になる可能性が高いです大文字小文字を区別せずに比較を行うには、LOWER() または UPPER() 関数を使用して、カラムの値と比較する値の両方を同じケースに変換します。
SELECT customer_id, name, city
FROM customers
WHERE LOWER(city) = 'new york';このクエリは、都市名が 'New York'、'new york'、'NEW YORK'、およびその他の大文字小文字のバリエーションである顧客をすべて返します。
8. パフォーマンスの考慮点
WHERE句を効率的に使用することは、クエリのパフォーマンスにとって極めて重要です。以下の点に注意してください。
- インデックス (Indexes): WHERE句で使用されるカラムにインデックスが作成されていることを確認してください。インデックスにより、データベースは一致する行を素早く特定でき、データ取得が高速化されます。インデックスについては後のモジュールで詳しく説明します。
- インデックスカラムでの関数の回避: WHERE句で
LOWER()のような関数をカラムに対して使用すると、データベースがインデックスを効果的に利用できなくなる場合があります。関数インデックス(Functional index)の使用を検討してください。 - 条件の順序: 最も選択性の高い条件(つまり、最も多くの行をフィルタリングできる条件)をWHERE句の最初に配置することを検討してください。特に AND を使用する場合、データベースの実行計画の最適化に寄与することがあります。
- 複雑なクエリの書き換え: パフォーマンス向上のために、複雑なWHERE句を簡素化したり書き換えたりすることが有効な場合があります。
EXPLAIN ANALYZEのようなツール(後述)を使用すると、PostgreSQLがどのようにクエリを実行しているかを把握し、パフォーマンスのボトルネックを特定するのに役立ちます。