「ゼロからはじめるデータベース操作」を読んで --- SQL操作を整理(第三章、四章)
本記事は、「ゼロからはじめるデータベース操作」を読んで --- SQL操作を整理(第一章、二章) の続きです。
集約と並び替え
テーブルを集約して検索する
SQLでデータに対して操作や計算を行うには、「関数」を使います。関数には以下のようなものがあります。
- COUNT : テーブルのレコード数(行数)を数える
- SUM : テーブルの数値列のデータを合計する
- AVG : テーブルの数値列を平均する
- MAX : テーブルの任意の列のデータの最大値を求める
- MIN : テーブルの任意の列のデータの最小値を求める
このような集計用の関数を、「集約関数」や「集合関数」と呼びます。以下に使用例を示します。
SELECT COUNT(*)
FROM my_table
()中は、引数になります。*という記号はNULLを含めたテーブルの全行を数えるためのものです。NULLを除外したい場合は、対象とする列を限定して引数に書きます。集約関数は、基本NULLを除外しますが、COUNT(*)は例外でNULLを除外しないことに注意が必要です。
SUM関数は、列の合計を求める関数です。NULLは無視して計算してくれます。
AVG関数は、列の平均値を求めます。この関数もNULLを無視して計算してくれます。
複数行の中から、最大値、最小値を求めるには、それぞれMAXとMIN関数を使用します。以下が使用例です。
SELECT MAX(cost), MIN(cost)
FROM products;
重複値を除外して集約関数を使用するには、DISTINCTキーワードを使います。以下に例を示します。
SELECT COUNT(DISTINCT category)
FROM priducts;
テーブルをグループに切り分ける
テーブルを何かしらの要素によってグループ分けするには、GROUP BY句を使用します。例えば、カテゴリーごとの行数を数えたければ、以下のようにします。
SELECT category, COUNT(*)
FROM products
GROUP BY category;
このようにすることで、カテゴリーごとの行数が表示されます。GROUP BY句に指定する列のことを集約キーやグループ化列と呼びます。また、集約キーにNULLが含まれていた場合、NULLというグループに分類されます。
GROUP BY句を使用するSELECT文でも、WHERE句を併用できますが、句の記述順に注意が必要です。
SELECT price, COUNT(*)
FROM products
WHERE category = 'book'
GROUP BY price;
FROM->WHERE->GROUP BY->SELECTの順で実行されます。
集約関数を使うときは、次の三つしかSELECT句に書くことが出来ません。
- 定数
- 集約関数
- GROUP BY句で指定した列名(集約キー)
つまり、以下のようなSELECT文はエラーになります。
SELECT name, price, COUNT(*)
FROM products
GROUP BY price;
nameという列がGROUP BY句にありません。また、GROUP BY句に列の別名は書けません。
SELECT category AS c, COUNT(*)
FROM products
GROUP BY c
このSQL文が実行できないのは、SELECT句よりもGROUP BY句の方が先に実行されるからです。
他のよくある間違いは、WHERE句に集約関数を書くことです。集約関数が書けるのは、SELECT句とHAVING句とORDER BY句だけです。
集約した結果に条件を指定する
WHERE句はレコード(行)に対しての条件指定でしたが、グループに対する条件指定にはHAVING句を使用します。HAVING句はGROUP BY句の後ろに書く必要があります。以下のように使用します。
SELECT category, COUNT(*)
FROM products
GROUP BY category
HAVING COUNT(*) = 2;
これは、categoryで集約したグループから、含まれる行数が2行のものを選択しています。
HAVING句に書くことのできる要素は、GROUP BY句を使った時のSELECT句と同じで、次の3つになります。
- 定数
- 集約関数
- GROUP BY句で指定した列名(集約キー) よって以下のSQL文は、エラーになります。
SELECT category, COUNT(*)
FROM products
GROUP BY category
HAVING name = 'book';
nameという列はGROUP BY句に含まれていません。
集約キーに対する条件は、WHERE句にもHAVING句にも書くことが出来ます。返す結果も同じです。しかし、WHERE句は行に対する条件指定、HAVING句はグループに対する条件指定なので、集約キーに対する条件はWHERE句に書くべきです。
検索結果を並べ替える
テーブルからデータを選択する際、行の順序を指定するには、SELECT文の文末にORDER BY句を付けます。ORDER句、SELECT文の最後に書きます。また、ORDER句に書く列名を「ソートキー」と呼びます。ORDER BY句は並び順を指定しない場合は暗黙的に昇順になっていますが、降順にしたい場合は列名の後ろにDESCキーワードを使用します。
ORDER BY句には、複数のソートキーを指定することができ、左側のキーから優先的に使用され、そのキーで同じ値が存在した場合に、右側のキーが参照されます。
NULLを含む列をソートキーに指定した場合、NULLは先頭または末尾にまとめて表示されます。
GROUP BY句では、列の別名を使えませんでしたが、ORDER BY句では使えます。それは、SELECT句よりORDER BY句の方が後に実行されるからです。
ORDER BY句には、テーブルに存在する列であれば、SELECT句に含まれていない列でも指定できます。
データの更新
テーブルにデータ(行)を登録するには、INSERT文を使用します。基本構文は以下の通りです。
INSERT INTO <テーブル名> (列1, 列2, 列3, ・・・) VALUES (値1, 値2, 値3, ・・・)
具体例を以下に示します。
INSERT INTO my_table (id, name, category, price) VALUES ('0001', 'pasta', 'food', 1200);
上記で示した、(id, name, category, price)の部分を列リスト、('0001', 'pasta', 'food', 1200)の部分を値リストと呼びます。 原則として、INSERT文は1回で1行を挿入するようにします。
テーブルの全列に対してINSERTを行う場合、列リストは省略することが出来ます。また、ある列にNULLを割り当てたい場合は、VALUES句の値リストにNULLをそのまま記述します。
列にデフォルト値を設定するには、CREATE TABLE文で、列に対してDEFAULT制約を付けます。以下に例を示します。
CREATE TABLE my_table
(id CHAR(4) NOT NULL,
price INTEGER DEFAULT 0,
ORIMARY KEY (id));
DEFAULTを設定した列は、INSERT文を使用する際、VALUES句にDEFAULTキーワードを指定するか、DEFAULTを設定した列を列リストとVALUESからも省略することでデフォルト値を挿入することが出来ます。つまり、以下の二通りで実装できます。
INSERT INTO my_table (id, price) VALUES ('0001', DEFAULT);
INSERT INTO my_table (id) VALUES ('0001');
(続きを執筆中・・・)
参考文献:
- ミック. SQL 第2版 ゼロからはじめるデータベース操作. 翔泳社. Kindle 版.