関係データベースに関する各種の定義や操作を行うためのデータベース用言語をSQL(Structured Query Language)という。
データベースの一部のデータが必要で、それを抽出する作業を問合せ(クエリ)と呼ぶ。
この問合せのために使用されるのがSELECT文である。
今回は、このSELECT文の基本的構造について観てみたい。
・SELECT文の基本
まずはSELECT文の書式である。
SELECT <列名リスト> 射影する列を指定
FROM <表名リスト> 問合せ対象の表を指定
WERER <条件式> 検索条件指定
GROUP BY <列名リスト> グループ化する列を指定
HAVING <条件式> グループに対する抽出条件指定
ORDER BY <列名リスト> 整列順指定
このSELECT文だが、実は上から順に読むのではない。
以下の表(社員表)を用いて解説しよう。
社員番号 | 氏名 | 基本給 | 部署 |
0001 | 川田 | 300,000 | 法人税 |
0002 | 佐藤 | 350,000 | 所得税 |
0003 | 木山 | 320,000 | 所得税 |
0004 | 谷原 | 380,000 | 税務訴訟 |
まずはこの表より、基本給35万円未満の社員の氏名と基本給を抜き出してみる。
SELECT 氏名,基本給
FROM 社員
WHERE 基本給<350000
と記述する。
まずFROM句で社員表を特定し、次にWHERE句で条件をチェックする。
基本給が35万円未満とあるので、それに合致する行を抜き出す。選択をするわけである。
この場合は、0001と0003だ。
社員番号 | 氏名 | 基本給 | 部署 |
0001 | 川田 | 300,000 | 法人税 |
0003 | 木山 | 320,000 | 所得税 |
選択により上図が抜き出される。
そして最後にSELECT文で指定した列を抜き出すのである。すなわち射影するわけだ。
指定の列は、氏名と基本給だから、
氏名 | 基本給 |
川田 | 300,000 |
木山 | 320,000 |
上記の表が問合せ結果となる。
FROM句で表を選び出し、WHERE句で条件の合う行を選択し、SELECT句で指定した列を抜き出す、というのが手順だ。
最初の実際にデータベースに格納している表を実表といい、今回の作業のように特定の行と列を抽出した仮想の表をビュー表という。
今度は違う条件を設定してみよう。
SELECT *
FROM 社員
WHERE 社員番号=`0001`
*はすべての列を示す。社員番号、氏名、基本給、部署コードの全部ということである。
FROM句で社員表を選び出し、WHERE句で社員番号が0001の行を選択し、SELECT文ですべての列を射影すると、
社員番号 | 氏名 | 基本給 | 部署 |
0001 | 川田 | 300,000 | 法人税 |
が出来てくる。
また列名を変更して抜き出すこともできる。
SELECT 社員番号,基本給*2 AS ボーナス
FROM 社員
AS句は別名をつけるときに使用される。
この例だと基本給を2倍したもの(*は掛け算を示す)をボーナスと改名する。
またWHERE句を省略すると、すべての行が対象となる。
このSELECT文を実行すると、
社員番号 | ボーナス |
0001 | 600,000 |
0002 | 700,000 |
0003 | 640,000 |
0004 | 760,000 |
と抽出される。
ボーナス列と金額が2倍されているのがポイントだ。
・表の結合
SELECT文で表を結合することができる。
二通りの方法がある。
①FROM句に表名を列記し、WHERE句に結合条件を記す
FROM句に結合したい表名を列記し、WHERE句に結合条件を記述すると、結合結果が得られる。
社員番号 | 氏名 | 基本給 | 部署コード |
0001 | 川田 | 300,000 | HZ |
0002 | 佐藤 | 350,000 | SZ |
0003 | 木山 | 320,000 | SZ |
0004 | 谷原 | 380,000 | ZS |
部署コード | 部署名 |
HZ | 法人税 |
SZ | 所得税 |
ZS | 税務訴訟 |
この2つの表を以下のSELECT文で結合する。
SELECT 社員.社員番号,社員.氏名,部署.部署名
FROM 社員,部署
WHERE 社員.部署コード=部署.部署コード
結合してできる表は、社員表の社員番号と氏名、部署表の部署名が列名として抽出される。
そして社員表と部署表の部署コードが等しい条件で結合する。
社員 社員番号 | 社員 氏名 | 社員 基本給 | 社員 部署コード | 部署 部署コード | 部署 部署名 |
0001 | 川田 | 300,000 | HZ | HZ | 法人税 |
0002 | 佐藤 | 350,000 | SZ | SZ | 所得税 |
0003 | 木山 | 320,000 | SZ | SZ | 所得税 |
0004 | 谷原 | 380,000 | ZS | ZS | 税務訴訟 |
社員表と部署表の部署コードは重複しているので、一つにまとめて表示される。
②JOINキーワードを用いる
結合は別の処理方法もある。
FROM句でJOINキーワードを用いるのである。
FROM表1 JOINH表2 ON<結合条件>
のように記述すると、双方の表を結合条件に従い結合する。
上図の社員表と部署表から同じ結果を得る場合は以下の通りである。
FROM 社員 JOIN 部署 ON 社員.部署コード=部署.部署コード
・グループ化
SQLを学ぶにあたり、最初の関門がGROUP BY句である。
これは、得られた行をある列の値ごとにグループ化し、グループごとの合計や平均値を計算することができる。
社員番号 | 氏名 | 基本給 | 部署 |
0001 | 岡田 | 500,000 | 歴史 |
0002 | 加治 | 700,000 | 歴史 |
0003 | 兵頭 | 450,000 | 税金 |
0004 | 大村 | 600,000 | 税金 |
この表に次にSQL文を実行する。
SELECT 部署,AVG(基本給)AS平均給与
FROM 社員
GROUP BY 部署
平均値を求める集合関数、AVGを使用して基本給の平均値を算出し、平均給与と改名して列表示する。
GROUP BY句で、部署でグループ化する。
SQLの実行順序は、FROM→GROUP BY→SELECTなので、
0001 | 岡田 | 500,000 | 歴史 |
0002 | 加治 | 700,000 | 歴史 |
0003 | 兵頭 | 450,000 | 税金 |
0004 | 大村 | 600,000 | 税金 |
のようにグループ化される。
SELECT句の集合関数により、それぞれの基本給の平均値が計算される。
歴史グループ=600,000
税金グループ=525,000
部署列と基本給改め平均給与で射影されるので、
部署 | 平均給与 |
歴史 | 600,000 |
税金 | 525,000 |
が抽出される。
SQL文では次のような集合関数が使用できる。
AVG(列名)=平均値を求める
MAX(列名)=最大値を求める
MIN(列名)=最小値を求める
SUM(列名)=合計を求める
COUNT(*)=行数を求める
集合関数COUNTのカッコ内の*はすべての列を示すが、具体的な列名を入れることもできる。
列名を指定した場合、その列の値がNULLでない行の数が得られる。
グループ化した行から特定の行のみを選択することもできる。
GROUP BY句の直後にHAVING句を指定する。
例として、社員表から2名以上の社員が属する部署の平均給与を抽出するためのSELECT文を挙げよう。
SELECT 部署,AVG(基本給)AS 平均給与
FROM 社員
GROUP BY 部署
HAVING COUNT(*)>=2
社員表を部署でグループ化し、そのグループのうち行数が2個以上を選択し、SELECT句で射影するのである。
グループ化する場合、守らないといけないルールがある。
GROUP BY句には、SELECT句やHAVING句に指定した集合関数の引数以外の列をすべて指定する、ということである。
換言すると、ある列をSELECTの結果やHAVING句の条件に含めたい場合は、冗長であったとしても、その列をGROUP by句に指定しないといけないということだ。
・整列
SELECT文では、結果の各行がどんな順序で並ぶかは保証されない。
整列させたい場合は、ORDER BY句で整列順を明示する必要がある。
ORDER BY句では、列名の後にASC(昇順、小さい順)またはDESC(降順、大きい順)を指定する。
これらを省略したときは、ASC(小さい順)を指定したものとみなされる。
ORDER BY <列名>[ASC | DESC],<列名>[ASC | DESC],・・
複数の列名を指定した場合は、まずは先頭に指定した第1整列キー順に行が並べられ、続いて第2整列キー、第3整列キーの順に整列される。
・後記
SQLの基本中の基本を概観したが、これは素人視点でも奥の深い世界だと感じられる。
まだまだ序の口。
データベースそしてSQLは知っておいて損は無さそうだ・・・!