今回は、テーブルからデータを抽出するときに検索条件を指定するための[WHERE]の使い方について説明します。
大量のデータを格納するRDBMSでは、通常、何の条件も指定せずにすべてのデータを抽出することはなく、目的に応じて抽出の条件指定をすることが普通です。
SQLの[WHERE]を使うことで、Excelのオートフィルタのように様々な条件指定をすることができます。
この記事では、SQLの[WHERE]を使った様々な条件指定の実例について説明します。
SQLは、汎用的なプログラミング言語と比較すると、主な命令語は4つしかなく非常に少ないことが特徴です。(SELECT、UPDATE、DELETE、INSERT)
SQLは命令語自体は少なくても修飾語を使うことで、RDBMSに対して様々な命令をすることができます。
その修飾語の中でも最も使用頻度が高いのが、SQLで条件指定をするための[WHERE句]です。
そもそもデータベースとは、扱うデータ量が多いことを理由として導入するものであり、データを参照・抽出する際に、条件指定をせず大量のすべてのデータを抽出することは基本的に行いません。
必然的に今記事で説明する[WHERE句]は、SQLの修飾語の中で最も使用される修飾語なのです。
Excel等の表計算ソフトをイメージすれば分かりやすいのですが、データを参照・抽出する際の条件指定には、様々な形式があります。
たとえば、下記のような条件です。
一般に、これらは、比較演算子や論理演算子を組み合わせて条件を具体的に表現することができます。SQLのWHEREも同様で、条件指定に応じた比較演算子・論理演算子をSQL文に記述する必要があります。
当記事では、主にSELECT文にWHERE区を組み合わせる実例で説明しますが、WHERE句は、SELECT以外でもUPDATE、DELETEでも使うことができます。
もう一つの基本文、INSERTでは使うことができません。INSERTは、新規レコードを追加するときに使うSQLであり、既存レコードに条件指定する動作は行わないためです。
WHEREは、SELECT ~ FROM ~ WHEREのように、それぞれの基本SQL文の後に記述しますが、WHERE以前の書き方は一緒です。
たとえば、SELECT文でWHEREを使う場合、WHEREの条件指定に関わらず、すべての列を抽出するのであれば、[SELECT * FROM]、特定の列のみ抽出するのであれば[SELECT name FROM]のように、WHERE以前の基本文法は変わりません。
SELECT * FROM Worker WHERE wage_rank < 4;
次章以降で、WHEREと比較演算子・論理演算子を組み合わせた様々な条件指定を説明しますが、実例のSQLコードは下記のテーブルを想定して記述します。
当記事のSQLを実際にお試ししたい方は、上記テーブルの元のcsvを準備していますので、ご自由にお使いください。ダウンロードや使用にあたって、一切の個人情報登録は不要です。(登録されている情報はランダム生成したものであり、実在する人物ではありません)
まずは、基本的な比較演算子から説明します。未満・超える・以下・以上や等しい・等しくないといった、比較演算子の基本的な記号群です。
< | 小なり |
> | 大なり |
<= | 以下 |
>= | 以上 |
= | 等しい |
<>または!= | 等しくない |
「<」は、『左辺は右辺より小さい(未満)』を表す演算子です。たとえば、給与ランク(wage_rank)が4より小さいレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank < 4; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank < 4; --name列のみを抽出
「>」は、『左辺は右辺より大きい(を超える)』を表す演算子です。たとえば、給与ランク(wage_rank)が3より大きいレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank > 3; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank > 3; --name列のみを抽出
「<=」は、『左辺は右辺の値以下』を表す演算子です。たとえば、給与ランク(wage_rank)が4以下のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank <= 4; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank <= 4; --name列のみを抽出
「>=」は、『左辺は右辺の値以上』を表す演算子です。たとえば、給与ランク(wage_rank)が3以上のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank >= 3; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank >= 3; --name列のみを抽出
「=」は、『左辺と右辺は等しい』を表す演算子です。たとえば、給与ランク(wage_rank)が3のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank = 3; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank = 3; --name列のみを抽出
「<>」または「!=」は、『左辺と右辺は等しくない』を表す演算子です。たとえば、給与ランク(wage_rank)が8以外のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE wage_rank <> 8; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank <> 8; --name列のみを抽出
または
SELECT * FROM Worker WHERE wage_rank != 8; --すべての列を抽出
SELECT name FROM Worker WHERE wage_rank != 8; --name列のみを抽出
この章では、汎用的な比較演算子(記号)を使って条件指定をするSQLについて説明しましたが、「=」や「<>」を使って対象のデータがNULLかどうかを判定することはできません。
たとえば、下記のようなSQLは望んでいる結果を出力してくれません(誤りです)。
× SELECT * FROM Worker WHERE position = NULL;
× SELECT * FROM Worker WHERE position <> NULL;
一見、正しい論理文に思えますが、NULLかどうかの判定は[IS NULL]や[IS NOT NULL]で記述する必要があります。次章で説明します。
次に、応用的な比較演算子の説明です。空白判定や指定文字を含むかどうかの判定、指定する最小値と最大値の間に収まっているか等、記号ではなく文字で表現する比較演算子です。
IS NULL | NULLのときにTRUE |
IS NOT NULL | NULLではないときにTRUE |
LIKE | 文字列がパターンに合致するときにTRUE |
BETWEEN | 値が〇以上かつ△以下のときにTRUE |
IN | 指定する値のいずれかと一致するときにTRUE |
NOT IN | 指定する値のいずれとも一致しないときにTRUE |
他にも、[ANY]や[ALL]という演算子がありますが、少し性質が異なります。そのため、[ANY]と[ALL]については、別記事で説明します。
「IS NULL」は、『NULLの場合にTRUE』を返す演算子です。たとえば、職位(position)がNULLのレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE position IS NULL; --すべての列を抽出
SELECT name FROM Worker WHERE position IS NULL; --name列のみを抽出
「IS NOT NULL」は、『NULLではない場合にTRUE』を返す演算子です。たとえば、職位(position)がNULLではないレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE position IS NOT NULL; --すべての列を抽出
SELECT name FROM Worker WHERE position IS NOT NULL; --name列のみを抽出
「LIKE」は、『文字列がパターン合致する場合にTRUE』を返す演算子です。
一般に、文字列の検索では一言一句マッチする「完全一致」と部分的にマッチする「部分一致」があります。
大量のデータベースから文字列を検索する場合には、圧倒的に「部分一致」を使う機会が多いのですが、LIKE区では下記のワイルドカードを使って部分一致検索を実行します。
_ | 任意の1文字 |
% | 任意の0文字以上の文字列 |
たとえば、住所(prefecture)に岐阜県という文字列を含んでいるレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE prefecture LIKE '岐阜県%'; --すべての列を抽出
SELECT name FROM Worker WHERE prefecture LIKE '岐阜県%'; --name列のみを抽出
当サイトの読者層はワイルドカードの概要をご理解されている方が多いと思うのですが、LIKE句のワイルドカードを用いた部分一致(あいまい検索)については、別記事で詳しく説明します。
「BETWEEN」は、『値が[基準値1]以上[基準値2]以下の場合にTRUE』を返す演算子です。たとえば、雇用年月日(hire_date)が2020-05-01以降かつ2020-09-30以下のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE hire_date BETWEEN '2020-05-01' AND '2020-09-30'; --すべての列を抽出
SELECT name FROM Worker WHERE hire_date BETWEEN '2020-05-01' AND '2020-09-30'; --name列のみを抽出
基準値が日付型の場合には、上記のように両端に「’」(シングルクォーテーション)が必要です。
「IN」は、『指定する値のいずれかと一致する場合にTRUE』を返す演算子です。たとえば、所属部署(department)が2か4のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE department IN (2,4); --すべての列を抽出
SELECT name FROM Worker WHERE department IN (2,4);; --name列のみを抽出
「IN」は、『指定する値のいずれとも一致しない場合にTRUE』を返す演算子です。たとえば、所属部署(department)が2か4以外のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE department NOT IN (2,4); --すべての列を抽出
SELECT name FROM Worker WHERE department NOT IN (2,4); --name列のみを抽出
最後は、論理演算子の説明です。SQL文に論理演算子を組み合わせることで、複数の条件指定をすることが可能になります。
AND | 両方の式がTRUEのときにTRUE |
OR | 片方の式がTRUEのときにTRUE |
NOT | TRUEならFALSE,FALSEならTRUE |
論理演算子については、優先順位や3つ以上の条件を組み合わせる場合など、複雑化する傾向がありますので、詳しくは別記事で説明します。
「AND」は、『両方の式がTRUEの場合にTRUE(かつ)』を返す演算子です。たとえば、雇用年月日(hire_date)が2020-7-31以前かつ所属部署が1のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE hire_date <= '2020-07-31' AND department = 1; --すべての列を抽出
SELECT name FROM Worker WHERE hire_date <= '2020-07-31' AND department = 1; --name列のみを抽出
「OR」は、『片方の式がTRUEの場合にTRUE(または)』を返す演算子です。たとえば、所属部署が5または給与ランク5以上のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE department = 5 or wage_rank >= 5; --すべての列を抽出
SELECT name FROM Worker WHERE department = 5 or wage_rank >= 5; --name列のみを抽出
「NOT」は、『TRUEの場合にFALSE、FALSEの場合にTRUE(または)』を返す演算子です。給与ランク(wage_rank)が8以外のレコードを抽出したいときには、下記のようにSQL文を実行します。
SELECT * FROM Worker WHERE NOT wage_rank = 8; --すべての列を抽出
SELECT name FROM Worker WHERE NOT wage_rank = 8; --name列のみを抽出
論理演算子の[NOT]は、比較演算子の[<>]または[!=]と同じ結果を返します。
前章までに、WHERE句で比較・論理演算子を使う場合のSQL文について説明しました。
この記事の最後に、WHEREの初歩的な概念・使い方について補足します。
基本的に、RDBMSのテーブル構造はExcelのようにデフォルトの行番号に基づいて順序付けがされている訳ではありません。
よって、SELECT・UPDATE・DELETE等とWHEREを組み合わせて対象の1行を特定するためには、主キー(PRIMARY KEY)を使うことが基本になります。
社員マスタで例えると、重複を許さない「社員番号」が主キーになるでしょう。
主キーがない場合には、氏名・生年月日・電話番号・住所等、複合的な条件で個人を特定するしかありません。
2016年に導入された[マイナンバー制度]は、要は国民ひとりひとりに主キーを振った制度です。個人のマイナンバーは、番号だけで個人を特定できる主キーです。
今回の記事では、WHEREを使って条件に合致したすべての列を抽出した実画面を掲載しましたが、本文で説明した通り、SQL文のWHERE以前の文法は変わりませんので、抽出する列は自由に指定することができます。
たとえば、上記のテーブルから所属部署(department)が2の社員番号(worker_id)と社員名(name)と所属部署(department)を抽出したい場合には、下記のSQLを実行します。
SELECT worker_id,name,department FROM Worker WHERE department = 2;
なお、この例では、所属部署(department)を条件指定のキーとしましたが、所属部署自体を抽出することは必須ではありません。下記のように、所属部署をキーにして、社員番号(worker_id)と社員名(name)のみを抽出することも可能です。
SELECT worker_id,name FROM Worker WHERE department = 2;
今回は、SQLのWHERE区について、比較演算子・論理演算子と組み合わせて、条件指定をするためのSQL文の基本について記事にしました。
本文で説明した通り、データベースは大量のデータを格納する基地になりますので、WHERE句を使った条件指定は、RDBMSの日々の運用で日常的に使う基本文になります。
今記事では基本的な内容に留めていますので、いくつかの演算子についての詳しい情報は、改めて当サイトで発信します。