連載
» 2012年01月13日 00時00分 公開

複数の条件を指定してSELECT文を実行する:Webブラウザで気軽に学ぶ実践SQL講座(4)

前回は、SELECT文の初歩の初歩を解説しました。今回は、複数の条件を指定して、目的のデータを取り出す方法を解説します(編集部)

[須々木尚子(すすき なおこ),日本オラクル]

しばらくはSELECT文をじっくりと

連載バックナンバー


 皆さま、あけましておめでとうございます。昨年末から始まったこの連載。まずはSELECT文の初歩を解説しました。いかがでしたでしょうか?

 本連載ではこれからしばらくの間、SELECT文のいろいろな使い方、つまりデータベースからデータを取り出すさまざまな方法を解説していきます。第1回でも申し上げましたが、SELECT文の構文はSQLの中で最も易しく、そして最も難しいものです。これは、SQL文の中でもSELECT文を利用する機会がかなり多いということも意味しています。ぜひ多くのSQL文を実際に試して、皆さんの力にしてください。

「AND」や「OR」を利用して条件を並べる

 今回は、複数の条件を指定したSELECT文の書き方を解説します。第3回で説明しましたが、SQL文で検索対象を「特定の行データのみ」に制限するには、条件を指定するキーワード「WHERE」を使用します。

 第3回の例では、条件は1つしか指定しませんでした。しかし、検索の条件は1つだけとは限りません。実際のアプリケーションでは、例えば、『「男性」であり「30代」である人』のように複数の条件を指定することの方が多いでしょう。

 複数の条件を指定するには、「WHERE」句と1つ目の条件に続いて「AND」や「OR」などの論理演算子を記述し、続いて2つ目の条件を指定します。ANDを使う場合、構文は以下の通りになります。

SELECT  列名1, 列名2,……
FROM    表名
WHERE   列名 比較演算子 条件値
AND     列名 比較演算子 条件値

 ORを使う場合は以下の通りになります。

SELECT  列名1, 列名2,……
FROM    表名
WHERE   列名 比較演算子 条件値
OR      列名 比較演算子 条件値

 前後2つの条件の間にANDを入れると、どちらも満たすという意味になり、「OR」を入れると2つの条件のどちらかを満たすという意味になります。これをベン図で表すと図1のようになります。

図1 ANDとORの意味を示したベン図 図1 ANDとORの意味を示したベン図

 ここで示した構文はあくまで基本的なものです。1つのSQL文の中に、ANDとORの両方の論理演算子を入れることや、ANDやORを複数指定することもできます。

 では、第2回で用意したSQL実行環境で、ANDやORを使ったSELECT文を実行してみましょう。例えば、EMP表のDEPTNO(部門)が20であり、かつJOB(職種)がMANAGERである社員を検索するには、以下のように条件を指定します。

SELECT  ename, deptno, job
FROM    emp
WHERE   deptno=20 AND job='MANAGER';

 実行すると図2のように結果が返ってきます。

図2 ANDを使ったSELECT文の実行結果 図2 ANDを使ったSELECT文の実行結果

 先に挙げたSELECT文のANDの部分をORに変えると、以下のようになります。

SELECT  ename, deptno, job
FROM    emp
WHERE   deptno=20 OR job='MANAGER';

 実行すると図3のように、DEPTNO(部門)が20である全社員と、JOB(職種)がMANAGERである全社員の両方が結果として返ってきます。

図3 ORを使ったSELECT文の実行結果 図3 ORを使ったSELECT文の実行結果

論理演算子の優先順位

 ANDやORを複数指定するときは、論理演算子の優先順位に注意しましょう。条件の書き方によっては、期待した結果を得られない可能性があるためです。

 例えば、「DEPTNO(部門)が20または30」であり、かつ「JOB(職種)がMANAGER」である社員(つまり部門20と30のそれぞれのマネージャ)を検索する場合を想定して、次のようなSELECT文を実行したとしましょう。

SELECT  ename, deptno, job
FROM    emp
WHERE   deptno=20 OR deptno=30 AND job='MANAGER';

 このSELECT文を実行すると図4のような結果になります。

図4 ANDとORの使い方を間違えた例 図4 ANDとORの使い方を間違えた例

 部門20と30のそれぞれのマネージャを検索したはずですが、結果を見ると「部門30のマネージャ」と「部門20の社員」が並んでいます。どうしてこのような結果になったのでしょうか?

 実は、WHERE句の中でANDとORを並べると、ANDの論理演算が優先するという決まりがあるのです。ANDよりもORを先に演算させたいときは、条件をカッコでくくります。こうすることで演算の優先順位を上げられるのです。

 ANDとORの優先順位を考えてSELECT文を書き直すと以下の通りになります。「部門30または部門20」という条件をカッコでくくって先に演算させて、その結果に対して「職種がマネージャである」という条件を演算させます。

SELECT  ename, deptno, job
FROM    emp
WHERE   (deptno=20 OR deptno=30) AND job='MANAGER';

 実行結果は図5のようになります。部門20と30のそれぞれのマネージャを検索できていることが分かります。

図5 カッコを使って、ORを先に演算させた結果 図5 カッコを使って、ORを先に演算させた結果

比較演算子はイコールだけではない

 ここまでの例では、WHERE句に「列=値」という形式、つまり比較演算子として等号(=)を使った形式で条件を指定してきました。しかし条件指定には等号のほかにも、大なり(>)や小なり(<)などの比較演算子も利用できます。表1はWHERE句の条件指定に利用できる主な比較演算子とそれぞれの意味をまとめたものです。

比較演算子 意味
= 等しい
>= 以上
> より大きい
<= 以下
< より小さい
<> または != 等しくない
BETWEEN a AND b a以上b以下
NOT BETWEEN a AND b a以上b以下を除いた部分
表1 WHERE句の条件指定に利用できる主な比較演算子

 例えば、「給与が3000以上の社員」を検索するには、以下のように比較演算子を使います。

SELECT ename, sal
FROM   emp
WHERE  sal >= 3000;

 実行すると図6のように3行のデータが返ってきます。

図6 比較演算子に不等号を使ったSELECT文の実行結果 図6 比較演算子に不等号を使ったSELECT文の実行結果

 表1に示したもののほかに、表2に示したような比較演算子も使えます。これらの比較演算子を使えば、文字列の部分一致検索なども可能になります。

比較演算子 意味
IN (A, B, C) A、B、Cのいずれか
NOT IN (A, B, C) A、B、Cのいずれにも一致しないもの
LIKE 'A%' Aで始まる任意の文字列
NOT LIKE 'A%' Aで始まる任意の文字列以外のもの
LIKE 'A_' Aとそれに続くもう1文字
NOT LIKE 'A_' Aとそれに続くもう1文字以外のもの
IS NULL NULL値であるもの
IS NOT NULL NULL値でないもの
表2 WHERE句の条件指定に利用できる比較演算子の中でも、数値比較以外の用途で便利に使えるもの

 IN演算子を使うと、特定の値をいくつか指定して、それに一致するデータを検索できます。例えば、先に挙げた例では「部門が20か30」という条件を指定するために、ORを使っていました。これは、INを使って次のように記述することもできます。

SELECT ename, deptno
FROM   emp
WHERE  deptno IN (20,30);

 このSELECT文を実行すると図7のようになります。

図7 ORを使って記述した条件をINで書き換えたSELECT文の実行結果 図7 ORを使って記述した条件をINで書き換えたSELECT文の実行結果

 この例では、INのあとのカッコに数値を入れていますが、文字列を入れて任意の文字列を検索することもできます。そのときは「IN ('A', 'B', 'C')」のように、文字列をシングルクオートで囲む必要があります。

 そして、比較演算子LIKEを使うと、 文字列の部分一致検索ができます。例えば、以下のようなSELECT文で、名前が「A」から始まる社員を検索できます。

SELECT ename
FROM   emp
WHERE  ename LIKE 'A%';

 実行すると、図8のように2件のデータが結果として戻ってきます。

図8 比較演算子にLIKEを使ったSELECT文の実行結果 図8 比較演算子にLIKEを使ったSELECT文の実行結果

「データがない」という条件

 リレーショナルデータベースでは、表のすべてのフィールドに必ず値が入っているとは限りません。「データが格納されていない」フィールドもあります。

 フィールドに値が入っていないことを、「NULLである」と表現します。例えば、EMP表の「COMM」列は歩合給を格納する列ですが、営業職以外の社員は歩合給をもらっていません。つまり、営業職以外の社員のCOMM列はNULLであると言えます。

 NULLの扱いはリレーショナルデータベース管理システム(RDBMS)の種類によっても異なりますが、Oracle Databaseでは「0(ゼロ)」という数値や、空白スペースとは異なるということに気を付けてください。そのため、対象がNULL値である場合、一般的な比較演算はできません。

 「データが格納されていない(NULLである)」という条件を指定するには、「IS NULL」演算子を使います。一方、「データが格納されている(NULLではない)」列を条件として指定する場合には、「IS NOT NULL」という演算子を使います。

 例えば、「歩合給をもらっている人(COMM列がNULLではない人)」を検索するには、以下のように条件を指定したSELECT文を実行します。

SELECT ename, job, comm
FROM   emp
WHERE  comm IS NOT NULL;

 実行すると、図9のように「JOB」列が「SALESMAN」となっている4行のデータ、つまり営業職の社員のデータを見ることができます。

図9 IS NOT NULL演算子を利用して、COMM列がNULLではないデータを取り出した結果 図9 IS NOT NULL演算子を利用して、COMM列がNULLではないデータを取り出した結果

論理演算子「NOT」

 表2を見ると、IS NOT NULLのほかにも「NOT」が入っている比較演算子があります。このNOTは、単に条件として使うだけでなく、ANDやORのように論理演算子として使うこともできます。例えば、以下のように使うと「給与が3000未満ではない」という条件を指定できます。

SELECT ename, sal
FROM   emp
WHERE  NOT (sal 

 このSELECT文を実行すると図10のように、給与が3000未満ではない、つまり給与が3000以上の社員データを取り出せます。

図10 3000未満という条件をNOTで否定してSELECT文を実行した結果 図10 3000未満という条件をNOTで否定してSELECT文を実行した結果

 以上、複数の条件を指定してSELECT文を実行する方法と、条件指定に利用できる論理演算子、比較演算子について解説しました。かなり多くの比較演算子を紹介しましたが、すべての実行例をお見せすることはできませんでした。ぜひ、さまざまな比較演算子を使ったSELECT文を作って実行してみてください。

コラム---コストを考えよう

 WHERE句で条件を指定する際、「この列で条件を指定しても、別の列で条件を指定しても、同じ結果になる」ということがあります。例えば、今回使用しているEMP表で社員番号7839のKINGさんのデータを検索するとき、「empno=7839」と指定しても、「ename='KING'」と指定しても同じ結果になります(ここでは、KINGさんが複数名いるかもしれないという可能性は考えないことにします)。

 このような場合、どちらの列で条件を指定するべきでしょうか? そのヒントになるのが「実行計画」と「コスト」です。

 実行計画とは、リレーショナルデータベース管理システムが、SQL文を実行する手順、計画を示すものです。そしてコストとは、その処理を行うために必要なリソース量を数値化したものです。簡単に言ってしまうと、この値が大きければ大きいほどSQL文の実行に時間がかかるということです。

 実行計画とコストは、APEXで確認できます。APEXの「実行計画」タブをクリックして、比較してみましょう。empno=7839と指定したSQL文の実行計画とコストは以下の図のようになります。図をクリックすると拡大図を表示します。

 一方、ename='KING'と指定したSQL文の実行計画とコストは以下の図のようになります。この図も、クリックすると拡大図を表示します。

 両者を比較すると、実行計画に違いがあることが分かります。この例では、「索引(インデックス)の有無」によって実行計画が変わっています。

 実行計画の読み方やコスト、そして索引については、いずれこの連載で説明しますが、基本的には「コストが低い方が効率が良い」と考えてください。この場合は、empnoを指定するとコストが「2」、enameを指定するとコストが「3」ですので、empnoを指定する方が効率が良いということになります。

 この例ではデータ量が少ないので、実行にかかる時間を比べてもほとんど差はありませんが、データ量が増えていくと、この差はどんどん大きくなります。

 アプリケーションの本番稼働が始まって、「遅い」と気付いた後で、効率の悪いSQL文を洗い出し、片っ端から修正しようとするという話はよくあります。しかし、一度本番稼働を始めたアプリケーションを後から修正するのは難しいものです。SQL文を書くときは、最初からコストを意識して書きたいものですね。


筆者紹介

日本オラクル オラクルダイレクト所属。

須々木尚子(すすき なおこ)

オンラインセミナーの講師や、お客様への提案、案件の支援などを担当。著書に「Oracle SQLクイズ」(翔泳社)があります。



Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。