前回は、SELECT文の初歩の初歩を解説しました。今回は、複数の条件を指定して、目的のデータを取り出す方法を解説します(編集部)
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
皆さま、あけましておめでとうございます。昨年末から始まったこの連載。まずはSELECT文の初歩を解説しました。いかがでしたでしょうか?
本連載ではこれからしばらくの間、SELECT文のいろいろな使い方、つまりデータベースからデータを取り出すさまざまな方法を解説していきます。第1回でも申し上げましたが、SELECT文の構文はSQLの中で最も易しく、そして最も難しいものです。これは、SQL文の中でもSELECT文を利用する機会がかなり多いということも意味しています。ぜひ多くのSQL文を実際に試して、皆さんの力にしてください。
今回は、複数の条件を指定した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つの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のように結果が返ってきます。
先に挙げたSELECT文のANDの部分をORに変えると、以下のようになります。
SELECT ename, deptno, job FROM emp WHERE deptno=20 OR job='MANAGER';
実行すると図3のように、DEPTNO(部門)が20である全社員と、JOB(職種)がMANAGERである全社員の両方が結果として返ってきます。
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のような結果になります。
部門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のそれぞれのマネージャを検索できていることが分かります。
ここまでの例では、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行のデータが返ってきます。
表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のようになります。
この例では、INのあとのカッコに数値を入れていますが、文字列を入れて任意の文字列を検索することもできます。そのときは「IN ('A', 'B', 'C')」のように、文字列をシングルクオートで囲む必要があります。
そして、比較演算子LIKEを使うと、 文字列の部分一致検索ができます。例えば、以下のようなSELECT文で、名前が「A」から始まる社員を検索できます。
SELECT ename FROM emp WHERE ename LIKE 'A%';
実行すると、図8のように2件のデータが結果として戻ってきます。
リレーショナルデータベースでは、表のすべてのフィールドに必ず値が入っているとは限りません。「データが格納されていない」フィールドもあります。
フィールドに値が入っていないことを、「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行のデータ、つまり営業職の社員のデータを見ることができます。
表2を見ると、IS NOT NULLのほかにも「NOT」が入っている比較演算子があります。このNOTは、単に条件として使うだけでなく、ANDやORのように論理演算子として使うこともできます。例えば、以下のように使うと「給与が3000未満ではない」という条件を指定できます。
SELECT ename, sal FROM emp WHERE NOT (sal
このSELECT文を実行すると図10のように、給与が3000未満ではない、つまり給与が3000以上の社員データを取り出せます。
以上、複数の条件を指定して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 © ITmedia, Inc. All Rights Reserved.