今回は、SQLのAND・ORの論理演算子を使った複数条件の検索方法について説明します。
データベースに格納された大量のデータから任意のデータを抽出するためには、単一の検索条件ではなく、複数の条件に合致するデータを抽出する機会も多くあります。
人事データベースでたとえれば、「勤続年数○以上かつ給与ランク△以上」といったような条件です。
SQLでは、ANDやORの論理演算子を使うことで、複数条件で検索することが可能になります。
この記事では、SQLのANDやORの基本的な使い方や、正確にデータを抽出するためのSQL文内における優先順位などを含め、実例を用いて説明します。
論理演算子AND・OR
汎用的なプログラミング言語と同様、SQLでも複数条件の設定には論理演算子のANDとORを使います。(NOTの詳細については当記事では割愛します)
優先順位
SQLの論理演算子では、下記のように優先順位が定められています。
- NOT
- AND
- OR
汎用的なプログラミング言語においては、プログラミングの3大要素「順次」という概念があり、コードの上から順番に実行されますが、SQLは「優先順位」という概念を基本としており、上から順番に実行されているわけではありません。
この記事では、論理演算子の優先順位について覚えておきましょう。NOT ⇒ AND ⇒ ORの順番です。
AND(かつ)の概要
ANDは、『2つの条件式の両方がTRUEの場合に、TRUE』を返します。
条件式1 | 条件式2 | AND判定結果 |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | FALSE |
FALSE | TRUE | FALSE |
FALSE | FALSE | FALSE |
日常的な例文
3年以上の会員継続かつ当月3,000円以上の購入の場合に、特典を付与
⇒両方の条件を満たす必要がある
OR(または)の概要
ORは、『2つの条件式の片方がTRUEなら、TRUE』を返します。
条件式1 | 条件式2 | OR判定結果 |
---|---|---|
TRUE | TRUE | TRUE |
TRUE | FALSE | TRUE |
FALSE | TRUE | TRUE |
FALSE | FALSE | FALSE |
日常的な例文
3年以上の会員継続または当月3,000円以上の購入の場合に、特典を付与
⇒どちらか一方の条件を満たしていればよい
SQL文_ANDの実例
この章では、AND区の基本文法と、実際のRDBMSでANDを使って複数条件のデータ検索をした実例を紹介します。
基本文法
SELECT * FROM テーブル名 WHERE 条件1 AND 条件2;
実際のSQL文
テーブルWorkerから、所属部署(department)が2 かつ 給与ランク(wage_rank)が4より大きいデータを抽出する場合のSQL文は下記の通りです。
SELECT * FROM Worker WHERE department = 2 AND wage_rank > 4;
MySQLのAND区の実例
PostgreSQLのAND区の実例
SQL文_ORの実例
この章では、OR区の基本文法と、実際のRDBMSでORを使って複数条件のデータ検索をした実例を紹介します。
基本文法
SELECT * FROM テーブル名 WHERE 条件1 OR 条件2;
実際のSQL文
テーブルWorkerから、所属部署(department)が3 または 職位(position)が5のデータを抽出する場合のSQL文は下記の通りです。
SELECT * FROM Worker WHERE department = 3 OR position = 5;
MySQLのOR区の実例
PostgreSQLのOR区の実例
ANDとORを組み合わせた複数条件
前章までに、SQLの論理演算子ANDとORの使い方について説明しました。
この章では、さらに応用的なSQL文、ANDとORを組み合わせた複数条件の実例を紹介します。両方の論理演算子を組み合わせる場合には、それぞれのSQL上の「優先順位」も意識しなければ、意図した結果を抽出することはできません。
実例_AND・OR複数条件の優先順位
下記の複数条件に合致するデータを抽出するSQL文を考えてみます。
雇用年月日が2020/06/01より前 または 所属部署が5 かつ 給与ランクが4以上 または 職位が4以下
この条件式は、大きく分類すると左辺かつ右辺の関係になり、蛍光ペンで色分けすると下記の通りになります。
雇用年月日が2020/06/01より前 または 所属部署が5 かつ 給与ランクが4以上 または 職位が4以下
誤ったSQL文
これをそのままSQL文で記述すると下記のようになると思います。
SELECT * FROM Worker WHERE hire_date < '2020-06-01' or department = 5 AND wage_rank >=4 or position <=4;
<実行結果>
この結果は、意図した正しい結果ではありません。下に表示されている表の「関根さん」は条件を満たしていないため、本来、検索結果として抽出されないはずです(2020/06/01より前は2020/06/01を含まない)。
これは、ANDとORの優先順位の関係で、SQLが下記のように解釈したことが原因です。
人間の意図
雇用年月日が2020/06/01より前 または 所属部署が5 かつ 給与ランクが4以上 または 職位が4以下
(AまたはB かつ CまたはD)
SQLの解釈
雇用年月日が2020/06/01より前 または 所属部署が5 かつ 給与ランクが4以上 または 職位が4以下
(Aまたは BかつC またはD)
結果として、中間の青の蛍光ペンの条件式は該当者がおらず、左右の緑の蛍光ペンの条件式の該当者のみが抽出されたのです。
正しいSQL文
当記事で説明した通り、SQLの論理演算子の優先順位は、NOT ⇒ AND ⇒ ORの順番です。
今回の例を正しくSQLで実行するためには、「()」(カッコ)を用いて、優先順位を操作する必要があります。
カッコで優先順位を操作
(雇用年月日が2020/06/01より前 または 所属部署が5) かつ (給与ランクが4以上 または 職位が4以下)
(AまたはB) かつ (CまたはD)
SELECT * FROM Worker WHERE (hire_date < '2020-06-01' or department = 5) AND (wage_rank >=4 or position <=4);
<実行結果>
これで正しい結果が抽出できました。
あとがき
今回は、SQLの論理演算子ANDとORの基本文法と優先順位の考え方について、実例を用いて記事にしました。
最後に紹介したSQLでは、論理的証明が不完全な箇所はありますが、カッコの有無(優先順位の変動)によって、結果が変わってくることはご理解いただけたかと思います。
SQLは、ご自身の手で実行することが上達の早道です。今回の内容は、当サイトの過去記事のテーブルを使っていますので、お試しいただきたい方は、下記記事を参考にすることで同じ環境を準備できますので、紹介しておきます。