連載
» 2012年01月25日 00時00分 UPDATE

Webブラウザで気軽に学ぶ実践SQL講座(5):SELECT文で取り出したデータを加工して表示する

前回までは、SELECT文でデータベースからデータを取り出すさまざまな方法を解説してきました。今回は、取り出したデータを加工して見やすくする方法を解説します(編集部)

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

データを加工して見やすくする

連載バックナンバー


 SELECT文には、データベースからデータを取り出すだけでなく、取り出したデータで計算をしたり、データを連結して表示したり、並べ替えて表示するといったこともできます。この機能をうまく使えば、SELECT文で取り出したデータを、ちょっとしたレポートの形にまとめられます。今回は、SELECT文の基本的な構文を使って、データの計算、加工、並べ替えの方法を解説します。

取り出したデータを対象に計算する

 SQL文の中には、「+」「-」「*」「/」といった算術演算子を指定することができます。これらの演算子を入れたSQL文を実行すると、データベースからデータを取り出し、取り出したデータを対象に四則演算をして、その結果をユーザーに返します。

 計算をすると言っても、取り出したデータを加工して表示しているだけであり、データベースのデータが書き換わるわけではありません。

 例えば、EMP表のSAL(給与)列に社員の月収が入っているとしましょう。月収を12倍すると、年収を求めることができます。以下のSELECT文を実行してみてください。

SELECT ename, sal, sal*12
FROM   emp;

 実行結果(図1)を見ると、SAL列の隣に、SAL列の値を12倍した値が並ぶ「SAL*12」という列が表示されます。

図1 SELECT文の中で乗算を実行した例 図1 SELECT文の中で乗算を実行した例

 計算対象となるのは、数値データだけではありません。日付データに対しても、「+」と「-」を使って加算と減算ができます。ただし、日付データに対して「*」や「/」を使うことはできません。

 例えば「入社して90日間は試用期間」であるとします。EMP表のHIREDATE(入社日)列に90を加算することで、試用期間が終了する日付を求めることができます。これを求めるには、次のSELECT文を実行してください。

SELECT ename, hiredate, hiredate+90
FROM   emp;

 図2のように、入社日と、試用期間が終了する日を確認できます。

図2 日付データを対象に加算を実行した例 図2 日付データを対象に加算を実行した例

 ここまで、データベースに格納された数値や日付データを対象に、計算をして表示する例を紹介しました。当たり前かもしれませんが、文字データに対して、加減乗除の演算子を付けても計算することはできません。プログラミング言語の中には、「+」が文字列の連結を意味するものもありますが、Oracle Databaseでは文字列連結には「||」を使用します。以下で、文字列連結の例を紹介します。

データベースから取り出したデータを連結する

 SELECT句に、複数の列をカンマ(,)区切りで指定すると、複数の列のデータを並べて表示することができます。しかし、単純に列のデータを表示するだけでなく、例えば「社員の姓の列と名前の列をつなげてフルネームにして表示したい」とか、「社員の名前に『さん』を付けて表示したい」ということもあるでしょう。

 SELECT文では、データベースから取り出した列データをつなげて表示したり、データに任意の定数(リテラル)を付け足して表示することができます。

 複数のデータやリテラルをつなげて表示するには連結演算子(||)を使います。SELECT句でデータ取得対象の列を列挙するときに、つなげたいデータが存在する列やリテラルの間に連結演算子を入れてください。基本的な構文は以下の通りです。

SELECT 列名 || 列名 || '文字列リテラル'
FROM   表名:

 文字列リテラルを指定するときは、シングルクオート(')で囲む必要があることに

注意してください。

 それでは、実際にデータベースから値を取り出して、文字列リテラルを連結して表示させてみましょう。EMP表のENAM(社員名)列に、文字リテラル「さん」を付けて表示することが

できます。以下のSELECT文を実行してみてください。

SELECT ename || 'さん'
FROM   emp;

 実行すると図3のように、社員名の末尾にすべて「さん」を付けて表示します。

図3 データベースから取り出したデータと文字列リテラルを連結させた例 図3 データベースから取り出したデータと文字列リテラルを連結させた例

 次は、社員名と役職をつなげて表示させてみましょう。EMP表のENAME(社員名)列とJOB(役職)列の前後に「さんは」と「です」という文字列リテラルをつなげて表示することによって、「KINGさんはPRESIDENTです」のような形式でデータを表示させることができます。次のSELECT文を実行してみてください。

SELECT ename || 'さんは' || job || 'です'
FROM   emp;

 実行すると図4のように、名前の後に「さんは」、役職の後に「です」をつなげた結果を表示することができます。

図4 データベースから取り出したデータと文字列リテラルを連結させて、名前と役職を文章のような形で表示させた例 図4 データベースから取り出したデータと文字列リテラルを連結させて、名前と役職を文章のような形で表示させた例

 次は、注意が必要な例を見てみましょう。EMP表のENAME(社員名)列とSAL(給与)列をつなげて表示し、「KING's salary is $5000」のように表示させてみましょう。ここまでに紹介した構文を使うと以下のようなSELECT文になると考えられます。

【エラーになる例】
SELECT ename || ''s salary is ' || sal
FROM   emp;

 しかし、これを実行すると図5のようにエラーになってしまいます。

図5 データと文字列を連結して表示させようとしてエラーになった例 図5 データと文字列を連結して表示させようとしてエラーになった例

 エラーの原因は、「社員名's」で使用しているアポストロフィー(')です。この符号は、文字列リテラルを囲むシングルクオートと同じものです。しかし、SELECT文を実行するリレーショナルデータベース管理システム(RDBMS)は、文字列リテラルを囲むシングルクオートと、文字として表示させたいアポストロフィーを区別できません。

 これを区別するには、文字列として表示させたいアポストロフィーに、もう1つアポストロフィーをつなげて「''」という形にします。これで、文字列リテラルを囲むシングルクオートではなく、文字として表示させたいアポストロフィーであると示すことができます。先に挙げた、エラーになってしまうSELECT文を書き直すと以下のようになります。

【正しく実行できる例】
SELECT ename || '''s salary is $' || sal
FROM   emp;

 実行すると、図6のようにアポストロフィーを表示できていることを確認できます。

図6 アポストロフィーを表示させた例 図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のように入社日が早い社員のデータを先にして並べたデータを表示することができます。

図7 ORDER BYの利用例。社員名を入社日順で表示させた例 図7 ORDER BYの利用例。社員名を入社日順で表示させた例

 データを降順にソートしたいときは、ORDER BY句でDESCを指定します。

 例えば、社員名を入社日が遅い順(降順)に表示するには、以下のSELECT文を実行します。

SELECT ename, hiredate
FROM   emp
ORDER BY hiredate DESC;

 実行すると、図8のように、最近に入社した社員のデータを先頭に、入社日が遅い順にデータが表示されます。

図8 ORDER BY句にDESCを指定してSELECT文を実行した例 図8 ORDER BY句にDESCを指定してSELECT文を実行した例

 ORDER BY句のソート列に、複数の列を指定することもできます。以下のSELECT文では、ORDER BY句で、給与(降順)と入社日(昇順)の2列を指定しています。実行して、結果を確認してみましょう。

SELECT ename, sal, hiredate
FROM   emp
ORDER BY sal DESC, hiredate ASC;

 実行すると、図9のように、取得されたデータが、まずは給与が高い順(降順)でソートされます。給与が同じデータについては、さらに、入社日が遅い順(昇順)にソートされて表示されます。

図9 ORDER BY句のソート列に、複数の列を指定したSELECT文を実行した結果 図9 ORDER BY句のソート列に、複数の列を指定したSELECT文を実行した結果

 今回は、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 列別名を使って、列の見出しに、表示しているデータを説明する言葉を入れた例 図a 列別名を使って、列の見出しに、表示しているデータを説明する言葉を入れた例

 上の例のように、列別名はデフォルトでは大文字で表示されます(列別名を小文字で指定しても、表示は大文字になります)。大文字と小文字を区別したり、スペースや特殊記号(#や$など)を含む列別名を使用するときは、ダブルクオート(")で列別名の前後を囲んでください。例えば、図aで使っている列別名「salary_report」を、大文字と小文字を区別した「Salary Report」という表記にしてみましょう。以下のSELECT文を実行してみてください。

SELECT ename || '''s salary is $' ||  sal AS "Salary Report"
FROM   emp;

 図bのように、大文字と小文字を区別した列別名が表示できました。また、「Salary」と「Report」の間にスペースが表示されていることにも注目してください。ダブルクオート(")を使用しない場合、スペースを含んだ列別名はエラーになります。

図b 大文字、小文字とスペースを使った列別名を指定した例 図b 大文字、小文字とスペースを使った列別名を指定した例

 列別名は、ソートをする際に、ORDER BY句で列名の代わりに指定することもできます。列別名をうまく使うと、表示を見やすくすることはもちろん、SQL文もシンプルにすることができます。


筆者紹介

r5susuki.jpg

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

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

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



Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

Touch Barという新UIを得た「MacBook Pro」、プレゼント!

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

RSSについて

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

メールマガジン登録

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