目次
SQL (Structured Query Language) とは、ユーザがDBMS (データベース管理システム)に指示を伝えるための言語です。
SQL にはDBMS に命令するための様々な命令文 が用意されています。
SQL の命令文は、以下の表のような役割を持つデータ定義言語 とデータ操作言語 に大別されます。
SQL の命令文
命令文の分類
役割
CREATE文 など
データ定義言語
スキーマ の定義 表の作成など
SELECT文 INSERT文 UPDATE文 DELETE文 など
データ操作言語
データの抽出・挿入 更新・削除等の操作
ユーザによって入力されたSQL の命令文を受けて、DBMS は該当するデータを抽出したり、返却したりする処理を行います。
命令文の書式
上の表にある通り、SQL には様々な命令文がありますが、それらを使う際には決められた書式に従う必要があります。
これ以降では、データベースの使用目的に合わせてSQL の命令文の書式を紹介ていきたいと思います。
データの抽出
SQL でデータベースから特定のデータを抽出するには、「SELECT文 」という命令文を使用します。
SELECT文とは、文字通り「選ぶ」という意味の「SELECT」から始まる文で、データベースから抽出したい内容に応じて以下の3点を指定します。
抽出する列名
抽出する表名
抽出する条件
(※必要無い場合は省略可)
このことを踏まえて、様々な抽出方法について取り上げていきたいと思います。
① 列の抽出(射影)
列を抽出する場合、まず最初に列名と表名を指定します。
列名は、SELECTの後に記入することで指定出来ます。
表名は、FROM句 という句の後に記入することで指定出来ます。
このような書式に従うと、SQL 文は次のようになります。
SELECT (列名)
FROM (表名)
例えば、以下のような商品表があるとします。
商品表
この表から商品名の列を抽出したい場合、SQL 文は次のようになります。
SELECT 商品名
FROM 商品表
このSQL 文による抽出結果は以下の通りです。
列の抽出
② 全ての列の抽出
表の全ての列を抽出する場合には、SELECTの後の列を指定する部分に「*(アスタリスク )」 を入れて次のようなSQL 文にします。
SELECT *
FROM (表名)
先ほどの商品表から全ての列を取り出したい場合、SQL 文は次のようになります。
SELECT *
FROM 商品表
このSQL 文による抽出結果は以下の通りです。
全ての列の抽出
③ 行の抽出(選択)
行を抽出する場合、先に列名と表名を指定し、その後WHERE句 という句を使って抽出したい行の条件を指定します。
条件を絞り込む必要がない場合は、WHERE句以降を省略することが出来ます。
このような書式に従うと、SQL 文は次のようになります。
SELECT (列名)
FROM (表名)
WHERE (条件)
WHERE句以降の条件の部分は、比較演算子 を用いて以下の表のように指定することが出来ます。
比較演算子
意味
例
=
左辺と右辺が等しい
単価=500 (単価が500円である)
>
左辺が右辺より大きい
単価>500 (単価が500円より大きい)
>=
左辺が右辺以上
単価>=500 (単価が500円以上)
<
左辺が右辺より小さい
単価<500 (単価が500円より小さい)
<=
左辺が右辺以下
単価<=500 (単価が500円以下)
<>
左辺と右辺が等しくない
単価<>500 (単価が500円でない)
例えば、商品表のうち、単価が500円以上となる商品の行を抜き出したいとします。
この場合、対象となる行全体を抽出するため、「*」を使って全ての列を指定します。そして、比較演算子 「>=」を使って次のようなSQL 文とします。
SELECT *
FROM 商品表
WHERE >= 500
このSQL 文による抽出結果は以下の通りです。
特定の行の抽出
④ 条件の組み合わせ
WHERE句以降で指定した条件は、論理演算子 を使って複数組み合わせることが出来ます。
例として、条件Aと条件Bという2つの条件がある場合の論理演算を取り上げたいと思います。
論理積 「(条件A)かつ(条件B)」
条件Aと条件Bの両方を満たす場合、つまり「(条件A)かつ(条件B)」を表現するには、論理積 「AND」を使って次のようなSQL 文にします。
SELECT (列名)
FROM (表名)
WHERE (条件A) AND (条件B)
例えば、商品表の中から単価が200円より大きく、かつ300円未満の商品の行を抽出したい場合、SQL 文は次のようになります。
SELECT *
FROM 商品表
WHERE 単価>200 AND 単価<300
このSQL 文による抽出結果は以下の通りです。
複数の条件による抽出 「AND(論理積 )」
論理和 「(条件A)または(条件B)」
条件Aと条件Bのいずれか一方を満たす場合、つまり「(条件A)または(条件B)」を表現するには、論理積 「OR」を使って次のようなSQL 文にします。
SELECT (列名)
FROM (表名)
WHERE (条件A) OR (条件B)
例えば、商品表の中から単価が200円以下、または3000円より大きい商品の行を抽出したい場合、SQL 文は次のようになります。
SELECT *
FROM 商品表
WHERE 単価<=200 OR 単価>3000
このSQL 文による抽出結果は以下の通りです。
複数の条件による抽出 「OR(論理和 )」
否定「(条件A)でない」
条件を満たしていない場合、つまり「(条件A)でない」を表現するためには、否定「NOT」を使って次のようなSQL 文にします。
SELECT (列名)
FROM (表名)
WHERE NOT (条件A)
これまで取り上げてきた3種類の演算子 には優先順位があり、
NOT > AND > OR
という順に優先されます。
例えば、「((条件A)かつ(条件B))の否定」を取ろうとして
NOT (条件A) AND (条件B)
とした場合、NOT演算子 はAND演算子 よりも優先されます。 そのため、条件Aと条件Bの両方に対してではなく、条件AのみにNOT演算子 が適用されます。
だから、「((条件A)の否定)かつ(条件B)」という結果になってしまいます。
このように、優先順位が低い演算子 を、優先順位が高い演算子 よりも先に適用させたい場合には、優先順位が低い演算子 を含む内容をカッコでひとまとまりにする と先に適用することが出来ます。
したがって、「((条件A)かつ(条件B))の否定」を取る場合には
NOT( (条件A)AND(条件B))
とすれば良いということになります。
このことを踏まえて、例えば、商品表から「単価が200円以下、または3000円より大きい」という条件を満たさない 商品の行を取得したい場合、SQL 文は次のようになります。
SELECT *
FROM 商品表
WHERE NOT (単価<=200 OR 単価>3000)
このSQL 文による抽出結果は以下の通りです。
複数の条件による抽出 「NOT(否定)」
表の結合
関係データベースでは、様々な表を組み合わせてデータを効率良く管理します。
そのためには、複数に分離した表を結合させる操作が必要になります。
SQL では、SELECT文のFROM句とWHERE句で結合したい表名と結合させる列名を指定すると、表同士を結合させることが出来ます。
例えば、表Aと表Bという2つの表を、表Aのcという列と表Bのcという列で結合させる場合、記号「,(コンマ)」、「.(ドット)」、「=(イコール)」を使い、SQL 文で次のように表現します。
SELECT (列名)
FROM 表A,表B
WHERE 表A.c = 表B.c
(※今回の例では「c」という、表Aと表Bに存在する同じ名前の列同士の結合を取り上げています。しかし、必ずしも結合する列名が同じでなければならないというわけではありません。)
(※また、結合する列名が異なっている場合、列名の違いから表を特定することが出来るため、「表A.c」のような「表名.」の部分を省略することが出来ます。)
例えば、商品の受注数を示した受注明細表と商品表を、「受注明細表の商品コード」列と「商品表の商品コード」列で結合させる場合、SQL 文は次のようになります。
SELECT *
FROM 受注明細表,商品表
WHERE 受注明細表.商品コード = 商品表.商品コード
このSQL 文による実行結果は以下の通りです。
表同士の結合
データの整列
これまでの方法で抽出したようなデータを整列させるためには、ORDER BY句 という句を使います。
具体的には、ORDER BY句以降で整列に使う列を指定し、さらに整列させる順番(昇順・降順)を指定します。
SQL 文は次のように表現します。
SELECT (列名)
FROM (表名)
WHERE (条件)
ORDER BY (整列に使う列名) ASC (※昇順) または DESC (※降順)
ORDER BY句の ASC は列を昇順 で並べ、DESC は降順 で並べます。
例えば、先ほどの「表同士の結合」で結合させた図を、さらに「単価」の列で昇順に整列させる場合、SQL 文は次のようになります。
SELECT *
FROM 受注明細表,商品表
WHERE 受注明細表.商品コード = 商品表.商品コード
ORDER BY 単価 ASC
このSQL 文による実行結果は以下の通りです。
表同士の結合と整列
このように、抽出結果のうち、1列を指定して整列させる以外にも、複数の列を指定して整列させることが出来ます。
例えば、結合させて新たに作られた表を、まず「数量」の列で昇順に整列させ、その状態からさらに「単価」で降順に整列させる場合、SQL 文は次のようになります。
SELECT *
FROM 受注明細表,商品表
WHERE 受注明細表.商品コード = 商品表.商品コード
ORDER BY 数量 ASC ,単価 DESC
このSQL 文による実行結果は以下の通りです。
表同士の結合と複数列の整列
関数による集計
SQL によってデータを抽出する際に、集計を行う集合関数 と呼ばれる関数があります。
以下の表のような集合関数を使うと、列の最大値や平均値、行数などを求めることが出来ます。
関数
役割
MAX(列名)
列の最大値 を求める
MIN(列名)
列の最小値 を求める
AVG (列名)
列の平均値 を求める
SUM(列名)
列の合計 を求める
COUNT(*)
行数 を求める
COUNT(列名)
値が入っている行数 を求める
集合関数を用いたSQL 文は次のように表現します。
SELECT (集合関数) (関数を用いる列名)
FROM (表名)
例えば、商品表の単価の最大値を求めたい場合、SQL 文は次のようになります。
SELECT MAX 単価
FROM 商品表
このSQL 文による実行結果は以下の通りです。
集合関数(MAX)の実行
データのグループ化と集合関数
列のうち、特定のカテゴリーや内容が一致するものを1つのグループにして扱いやすくすることをグループ化 と呼びます。
グループ化は、GROUP BY句 という句を用います。
具体的には、GROUP BY句の後にグループ化したい列名を指定します。
こうすることで、指定した列のうち、特定のカテゴリーや内容が一致するものを1つのグループにすることが出来ます。
さらに、グループ化によってまとめられたデータに対し、集合関数を用いるとグループ単位でデータの特徴を求めることが出来ます。
グループ化と集合関数を用いたSQL 文は次のようになります。
SELECT (グループ化したい列名), (集合関数)
FROM (表名)
GROUP BY (グループ化したい列名)
例えば、商品のカテゴリーを示す「カテゴリー」列がある商品表をカテゴリーごとに分類し、各カテゴリーに属する商品数を数える場合、SQL 文は次のようになります。
SELECT カテゴリー, count(*)
FROM 商品表
GROUP BY カテゴリー
このSQL 文による実行結果は以下の通りです。
データのグループ化
グループ化と絞り込み
データをグループ化した後、各グループに対し一定の条件を設けて絞り込みを行うことが出来ます。
絞り込みは、HAVING句 を使用します。
具体的には、先ほどのグループ化のSQL 文の後にHAVING句を記入し、さらにその後に続けて絞り込みを行うための条件を指定します。
絞り込むための条件は集合関数や比較演算子 を組み合わせて表現します。
グループ化と絞り込みを用いたSQL 文は次のようになります。
SELECT (グループ化したい列名), (集合関数)
FROM (表名)
GROUP BY (グループ化したい列名)
HAVING (絞り込み条件)
例として、先ほどの商品表を取り上げたいと思います。
まず、先ほどの「データのグループ化」と同様に、商品をカテゴリーごとにグループ化します。
そして、集合関数AVG を用いて各カテゴリーの平均単価を求めます。
さらに、HAVING句で平均単価が2000円より大きいという条件を指定し、この条件を満たすグループを絞り込みたいと思います。
SELECT カテゴリー, AVG (単価)
FROM 商品表
GROUP BY カテゴリー
HAVING AVG (単価) > 2000
このSQL 文による実行結果は以下の通りです。
データのグループ化と絞り込み
この過程の図では、消耗品以外のカテゴリーの平均単価については触れられていないため、全カテゴリーの平均単価を以下の図に示します。
各カテゴリーの平均単価
参考にさせて頂いた書籍
きたみりゅうじ 『キタミ式イラストIT塾 基本情報技術者 平成31/01年』 技術評論社 2019年
学習してみて
今回は、データベースを操作するための言語、SQL について学習しました。
データベースを自在に操作することができる分、基本的な句だけでも色々なものがありますね。
基本的な操作をある程度把握したら使い慣れるまで繰り返し練習してみるのが一番良いのではないかと思います。
データを扱うことが出来るようになれば、様々なデータの傾向を掴んだり、直感では分からないような因果関係・相関関係を明らかにすることが出来ると思います。
様々な可能性のある領域で、個人的にも興味のある領域なので、今後もますます学習を深めていきたい領域だと感じました。