前回までは、SELECT文でデータベースからデータを取り出すさまざまな方法を解説してきました。今回は、取り出したデータを加工して見やすくする方法を解説します(編集部)
SELECT文には、データベースからデータを取り出すだけでなく、取り出したデータで計算をしたり、データを連結して表示したり、並べ替えて表示するといったこともできます。この機能をうまく使えば、SELECT文で取り出したデータを、ちょっとしたレポートの形にまとめられます。今回は、SELECT文の基本的な構文を使って、データの計算、加工、並べ替えの方法を解説します。
SQL文の中には、「+」「-」「*」「/」といった算術演算子を指定することができます。これらの演算子を入れたSQL文を実行すると、データベースからデータを取り出し、取り出したデータを対象に四則演算をして、その結果をユーザーに返します。
計算をすると言っても、取り出したデータを加工して表示しているだけであり、データベースのデータが書き換わるわけではありません。
例えば、EMP表のSAL(給与)列に社員の月収が入っているとしましょう。月収を12倍すると、年収を求めることができます。以下のSELECT文を実行してみてください。
SELECT ename, sal, sal*12 FROM emp;
実行結果(図1)を見ると、SAL列の隣に、SAL列の値を12倍した値が並ぶ「SAL*12」という列が表示されます。
計算対象となるのは、数値データだけではありません。日付データに対しても、「+」と「-」を使って加算と減算ができます。ただし、日付データに対して「*」や「/」を使うことはできません。
例えば「入社して90日間は試用期間」であるとします。EMP表のHIREDATE(入社日)列に90を加算することで、試用期間が終了する日付を求めることができます。これを求めるには、次のSELECT文を実行してください。
SELECT ename, hiredate, hiredate+90 FROM emp;
図2のように、入社日と、試用期間が終了する日を確認できます。
ここまで、データベースに格納された数値や日付データを対象に、計算をして表示する例を紹介しました。当たり前かもしれませんが、文字データに対して、加減乗除の演算子を付けても計算することはできません。プログラミング言語の中には、「+」が文字列の連結を意味するものもありますが、Oracle Databaseでは文字列連結には「||」を使用します。以下で、文字列連結の例を紹介します。
SELECT句に、複数の列をカンマ(,)区切りで指定すると、複数の列のデータを並べて表示することができます。しかし、単純に列のデータを表示するだけでなく、例えば「社員の姓の列と名前の列をつなげてフルネームにして表示したい」とか、「社員の名前に『さん』を付けて表示したい」ということもあるでしょう。
SELECT文では、データベースから取り出した列データをつなげて表示したり、データに任意の定数(リテラル)を付け足して表示することができます。
複数のデータやリテラルをつなげて表示するには連結演算子(||)を使います。SELECT句でデータ取得対象の列を列挙するときに、つなげたいデータが存在する列やリテラルの間に連結演算子を入れてください。基本的な構文は以下の通りです。
SELECT 列名 || 列名 || '文字列リテラル' FROM 表名:
文字列リテラルを指定するときは、シングルクオート(')で囲む必要があることに
注意してください。
それでは、実際にデータベースから値を取り出して、文字列リテラルを連結して表示させてみましょう。EMP表のENAM(社員名)列に、文字リテラル「さん」を付けて表示することが
できます。以下のSELECT文を実行してみてください。
SELECT ename || 'さん' FROM emp;
実行すると図3のように、社員名の末尾にすべて「さん」を付けて表示します。
次は、社員名と役職をつなげて表示させてみましょう。EMP表のENAME(社員名)列とJOB(役職)列の前後に「さんは」と「です」という文字列リテラルをつなげて表示することによって、「KINGさんはPRESIDENTです」のような形式でデータを表示させることができます。次のSELECT文を実行してみてください。
SELECT ename || 'さんは' || job || 'です' FROM emp;
実行すると図4のように、名前の後に「さんは」、役職の後に「です」をつなげた結果を表示することができます。
次は、注意が必要な例を見てみましょう。EMP表のENAME(社員名)列とSAL(給与)列をつなげて表示し、「KING's salary is $5000」のように表示させてみましょう。ここまでに紹介した構文を使うと以下のようなSELECT文になると考えられます。
【エラーになる例】 SELECT ename || ''s salary is ' || sal FROM emp;
しかし、これを実行すると図5のようにエラーになってしまいます。
エラーの原因は、「社員名's」で使用しているアポストロフィー(')です。この符号は、文字列リテラルを囲むシングルクオートと同じものです。しかし、SELECT文を実行するリレーショナルデータベース管理システム(RDBMS)は、文字列リテラルを囲むシングルクオートと、文字として表示させたいアポストロフィーを区別できません。
これを区別するには、文字列として表示させたいアポストロフィーに、もう1つアポストロフィーをつなげて「''」という形にします。これで、文字列リテラルを囲むシングルクオートではなく、文字として表示させたいアポストロフィーであると示すことができます。先に挙げた、エラーになってしまうSELECT文を書き直すと以下のようになります。
【正しく実行できる例】 SELECT ename || '''s salary is $' || sal FROM emp;
実行すると、図6のようにアポストロフィーを表示できていることを確認できます。
データベースに格納されているデータは、どのような順番に並んでいるのでしょう。データの小さい順でしょうか。データを入れた順でしょうか。
実は、決まった順番はありません。Oracle Databaseでは、データを効率よく格納するために、「空いている」領域にデータを書き込んでいくのです。そのため、必ずしも連番でデータが格納されているわけではありません。同様に、データを取り出すときにも、特定の列データに注目して並べ替えるようなことはしません。つまり、SELECT文で取り出したデータの並び順には、何の規則もないのです。
アプリケーションのバージョンアップや、データの再編成などのメンテナンスがきっかけで、データの表示順が変わって困ったという話を聞くこともあります。しかし、先に述べたようにデータベースが格納しているデータは決まった順番で並んでいるわけではありません。メンテナンス前は、「たまたま」その順番でアプリケーションがデータを表示していただけであり、常にその順番で表示するという保証はないのです。
では、特定のルールに従う形でデータを表示させたい場合はどうすれば良いのでしょうか。ここでは、「ORDER BY」句を使って、データを昇順、あるいは降順でソート(並べ替え)する方法を説明します。
SELECT文でORDER BY句を使うときの基本的な構文は以下の通りです。
SELECT 列名, 列名, … FROM 表名 WHERE 列名 =(比較演算子) 値 ORDER BY ソート列 (ASC / DESC)
ORDER BY句に、データをソートする際に基準とする列を指定し、昇順(Ascending)なら「ASC」、降順(descending)なら「DESC」を付け加えます。「ASC」「DESC」を指定しないと、デフォルトで昇順(ASC)に並べ替えられます。
例えば、社員名を入社日順、つまり昇順で表示するには、以下のSELECT文を実行します。
SELECT ename, hiredate FROM emp ORDER BY hiredate;
実行すると、図7のように入社日が早い社員のデータを先にして並べたデータを表示することができます。
データを降順にソートしたいときは、ORDER BY句でDESCを指定します。
例えば、社員名を入社日が遅い順(降順)に表示するには、以下のSELECT文を実行します。
SELECT ename, hiredate FROM emp ORDER BY hiredate DESC;
実行すると、図8のように、最近に入社した社員のデータを先頭に、入社日が遅い順にデータが表示されます。
ORDER BY句のソート列に、複数の列を指定することもできます。以下のSELECT文では、ORDER BY句で、給与(降順)と入社日(昇順)の2列を指定しています。実行して、結果を確認してみましょう。
SELECT ename, sal, hiredate FROM emp ORDER BY sal DESC, hiredate ASC;
実行すると、図9のように、取得されたデータが、まずは給与が高い順(降順)でソートされます。給与が同じデータについては、さらに、入社日が遅い順(昇順)にソートされて表示されます。
今回は、SELECT文で取り出したデータを加工して表示する方法を紹介しました。単に列データをそのまま表示するだけではなく、データを使って計算したり、複数の列やリテラルを連結してレポートのように表示したり、ソートして表示することができます。今回ご紹介した例のほかにも、「こう書き換えたらどうなるかな?」と考えて、ぜひいろいろなSELECT文を書いて実行してみてください。
今回は、SELECT句の中で四則演算を実行する例や、連結演算子でデータを連結して表示する例などを見てきました。ここまでは結果データに注目してきましたが、列の「見出し」に注目してみましょう。
SELECT文で指定した計算式や連結演算子がそのまま表示されているので、見栄えが良くありません。もちろん、見栄えだけの問題ではありません。計算結果を表示する列を指定してソートを実行するときに、ORDER BY句の記述が煩雑になるという問題もあります。
そこで、このような列には「列別名」を付けて、分かりやすい表示にすることをお勧めします。
Oracle Databaseで列別名を使うには、SELECT句で列名を列挙するときにちょっと記述を加えます。列別名を付けたい列の後に、ASキーワードを挟んで列別名として使いたい名前を指定するのです。ASキーワードは省略することもできます。基本となる構文は以下の通りです。
SELECT 列名 AS 列別名, 列名 列別名, … FROM 表名 WHERE 列名 =(比較演算子) 値 ORDER BY ソート列 (ASC / DESC)
実際に試してみましょう。EMP表のENAME(社員名)列とSAL(給与)列をつなげて表示し、「KING's salary is $5000」のように表示させてみます。図6でお見せした例ですね。ただし、今度は列別名を付けて、列の見出しを分かりやすいものにしてみます。以下のSELECT文を実行してみてください。
SELECT ename || '''s salary is $' || sal AS salary_report FROM emp;
実行すると、図aのように、列の見出しが「salary_report」となります。図6と見比べてください。こちらの方がどういうデータを表示しているのか分かりやすいですね。
上の例のように、列別名はデフォルトでは大文字で表示されます(列別名を小文字で指定しても、表示は大文字になります)。大文字と小文字を区別したり、スペースや特殊記号(#や$など)を含む列別名を使用するときは、ダブルクオート(")で列別名の前後を囲んでください。例えば、図aで使っている列別名「salary_report」を、大文字と小文字を区別した「Salary Report」という表記にしてみましょう。以下のSELECT文を実行してみてください。
SELECT ename || '''s salary is $' || sal AS "Salary Report" FROM emp;
図bのように、大文字と小文字を区別した列別名が表示できました。また、「Salary」と「Report」の間にスペースが表示されていることにも注目してください。ダブルクオート(")を使用しない場合、スペースを含んだ列別名はエラーになります。
列別名は、ソートをする際に、ORDER BY句で列名の代わりに指定することもできます。列別名をうまく使うと、表示を見やすくすることはもちろん、SQL文もシンプルにすることができます。
日本オラクル オラクルダイレクト所属。
須々木尚子(すすき なおこ)
オンラインセミナーの講師や、お客様への提案、案件の支援などを担当。著書に「Oracle SQLクイズ」(翔泳社)があります。
Copyright © ITmedia, Inc. All Rights Reserved.