SELECTとFROMの間の(FROMがない場合は最後まで)データの並びのことを選択リストという。
SELECTの結果の行の順序は、指定しない限り保証されない。順序の指定はORDER BYを使用する。
SELECT 選択リスト FROM テーブル名 ORDER BY 列名 [DESC], 列名 [DESC], ...
先に指定された列ほど優先される。DESC指定の列は降順、それ以外は昇順となる。
ORDER BYの例(デフォルトはASC指定の昇順)
oddtbs=> select * from student order by num, cnum, gnum; gnum | cnum | num | name | gender | blood | score ------+------+-----+--------------+--------+-------+------- 1 | 1 | 1 | 大石友美 | 2 | O | 63 2 | 1 | 1 | 大塚千恵子 | 2 | A | 56 3 | 1 | 1 | 大沼ゆう子 | 2 | A | 47 1 | 2 | 1 | 石川大地 | 1 | O | 74 2 | 2 | 1 | 石田美奈 | 2 | A | 67 3 | 2 | 1 | 石橋直晃 | 1 | A | 58 1 | 3 | 1 | 瀧下健介 | 1 | B | 82 ... ... 1 | 4 | 6 | 岡村ひろ子 | 2 | O | 80 2 | 4 | 6 | 岡本暁 | 1 | B | 76 3 | 4 | 6 | 梶間昇平 | 1 | B | 58 (72 rows) oddtbs=> select * from student order by num asc, cnum asc, gnum asc; 結果は先ほどと同じ。
降順の例
oddtbs=> select * from student order by num desc, cnum, gnum desc;
gnum | cnum | num | name | gender | blood | score
------+------+-----+--------------+--------+-------+-------
3 | 1 | 6 | 長崎アキノリ | 1 | A | 54
2 | 1 | 6 | 長田めぐみ | 2 | A | 51
1 | 1 | 6 | 藤田智子 | 2 | A | 68
3 | 2 | 6 | 渥美巖 | 1 | AB | 61
2 | 2 | 6 | 井上沙織 | 2 | A | 80
1 | 2 | 6 | 伊東初音 | 2 | A | 54
3 | 3 | 6 | 加藤勝 | 1 | B | 48
...
...
3 | 4 | 1 | 増田佳乃 | 2 | O | 57
2 | 4 | 1 | 増田由利香 | 2 | O | 64
1 | 4 | 1 | 浅原丞 | 1 | O | 69
(72 rows)
グループ化とはある列、または列の集合が同じ値である行を1行で表示するという機能である。
グループ化するにはGROUP BYを使用する。
グループ化すると集約関数を使用することができる。
集約関数とは複数の値から1つの値を返すような関数である。
SELECT 選択リスト FROM テーブル名 GROUP BY 列の並び [ORDER BY];
選択リストに記述できるのは、GROUP BYで指定した列か集約関数(またはそれらを加工したデータ)のみ
集約関数 | 意味 |
---|---|
COUNT | 行数 |
MIN | 最小値 |
MAX | 最大値 |
SUM | 合計 |
AVG | 平均 |
gnumでグループ化
oddtbs=> select gnum, avg(score) from student group by gnum;
gnum | avg
------+---------------------
1 | 67.8333333333333333
2 | 67.0416666666666667
3 | 67.6250000000000000
(3 rows)
GROUP BYで指定した列と、集約関数以外のデータをSELECTで指定
oddtbs=> select gnum, cnum, avg(score) from student group by gnum;
ERROR: column "student.cnum" must appear in the GROUP BY clause or be used in an aggregate function
※ エラーとなる
複数列でグループ化
oddtbs=> select gnum, cnum, avg(score) from student group by gnum, cnum;
gnum | cnum | avg
------+------+---------------------
3 | 3 | 81.0000000000000000
3 | 1 | 67.0000000000000000
3 | 2 | 65.6666666666666667
1 | 3 | 71.1666666666666667
2 | 3 | 61.3333333333333333
1 | 1 | 66.8333333333333333
1 | 2 | 65.8333333333333333
2 | 1 | 64.1666666666666667
2 | 2 | 75.8333333333333333
3 | 4 | 56.8333333333333333
1 | 4 | 67.5000000000000000
2 | 4 | 66.8333333333333333
(12 rows)
GROUP BYなしで集約関数を使用
oddtbs=> select avg(score) from student;
avg
---------------------
67.5000000000000000
(1 row)
※ GROUP BYなしで集約関数を使用した場合は全体が1つのグループになる。
集約関数を含む条件(HAVING)
次のSQLをファイルとして作成し実行。(having071.sql)
oddtbs=> \i having071.sql
gnum | cnum | avg
------+------+---------------------
1 | 1 | 66.8333333333333333
1 | 2 | 65.8333333333333333
1 | 3 | 71.1666666666666667
1 | 4 | 67.5000000000000000
2 | 2 | 75.8333333333333333
2 | 4 | 66.8333333333333333
3 | 1 | 67.0000000000000000
3 | 2 | 65.6666666666666667
3 | 3 | 81.0000000000000000
(9 rows)
※ 集約関数を含む条件式はHAVING句で指定する(WHEREは使用できない)。
COUNT関数
oddtbs=> select count(*) from student; count ------- 72 (1 row) oddtbs=> select blood, count(*) from student group by blood order by blood; blood | count -------+------- A | 33 AB | 7 B | 13 O | 19 (4 rows) oddtbs=> select gnum, blood, count(*) from student group by gnum, blood order by gnum, blood; gnum | blood | count ------+-------+------- 1 | A | 11 1 | AB | 2 1 | B | 3 1 | O | 8 2 | A | 13 2 | AB | 1 2 | B | 6 2 | O | 4 3 | A | 9 3 | AB | 4 3 | B | 4 3 | O | 7 (12 rows)
OFFSETやLIMITを使用してSELECTの結果の行数を制限することができる。
OFFSETはスキップする、LIMITは表示する行数である。
SELECT ... [OFFSET スキップする行数] [LIMIT 表示する行数];
OFFSETを省略すると先頭から、LIMITを省略すると最後までとなる。
oddtbs=> select * from student order by score desc offset 62; gnum | cnum | num | name | gender | blood | score ------+------+-----+------------+--------+-------+------- 2 | 3 | 1 | 川口英記 | 1 | A | 51 2 | 2 | 5 | 櫻井梨江 | 2 | A | 50 2 | 3 | 4 | 鈴木クミ | 2 | A | 49 2 | 4 | 4 | 鈴木崇宏 | 1 | B | 48 1 | 1 | 2 | 中村優作 | 1 | O | 48 3 | 3 | 6 | 加藤勝 | 1 | B | 48 3 | 1 | 1 | 大沼ゆう子 | 2 | A | 47 2 | 3 | 6 | 碓井浩 | 1 | B | 46 3 | 2 | 4 | 鈴木雄太 | 1 | AB | 45 3 | 4 | 4 | 鷲山綾子 | 2 | B | 45 (10 rows) oddtbs=> select * from student order by score desc limit 10; gnum | cnum | num | name | gender | blood | score ------+------+-----+------------+--------+-------+------- 1 | 1 | 3 | 北川陽子 | 2 | A | 94 3 | 1 | 4 | 尾原裕基 | 1 | A | 93 3 | 3 | 4 | 鈴木貴大 | 1 | O | 93 3 | 3 | 3 | 八木島時史 | 1 | O | 92 3 | 3 | 1 | 池田綾乃 | 2 | A | 92 3 | 2 | 2 | 村上和美 | 2 | A | 91 2 | 2 | 4 | 矢野明恵 | 2 | B | 91 3 | 3 | 2 | 西山隆弘 | 1 | O | 91 2 | 3 | 5 | 土屋いつ恵 | 2 | A | 89 2 | 2 | 2 | 正守貴世 | 2 | A | 86 (10 rows) oddtbs=> select * from student order by score desc offset 10 limit 10; gnum | cnum | num | name | gender | blood | score ------+------+-----+------------+--------+-------+------- 2 | 1 | 3 | 片瀬優富子 | 2 | A | 86 1 | 3 | 1 | 瀧下健介 | 1 | B | 82 2 | 2 | 3 | 片山マリコ | 2 | A | 81 1 | 2 | 4 | 服部圭祐 | 1 | B | 81 1 | 4 | 6 | 岡村ひろ子 | 2 | O | 80 2 | 3 | 2 | 曽根尚子 | 2 | A | 80 2 | 2 | 6 | 井上沙織 | 2 | A | 80 2 | 4 | 6 | 岡本暁 | 1 | B | 76 3 | 2 | 5 | 渡部優子 | 2 | AB | 76 2 | 4 | 5 | 田原直彦 | 1 | A | 76 (10 rows) oddtbs=> select * from student order by score desc offset 20 limit 10; gnum | cnum | num | name | gender | blood | score ------+------+-----+------------+--------+-------+------- 3 | 2 | 5 | 渡部優子 | 2 | AB | 76 1 | 1 | 5 | 木村葉子 | 2 | AB | 75 1 | 2 | 1 | 石川大地 | 1 | O | 74 2 | 1 | 4 | 平野今日子 | 2 | B | 74 1 | 3 | 5 | 湯浅茂 | 1 | O | 73 3 | 1 | 5 | 油井順一 | 1 | B | 72 3 | 4 | 3 | 文倉翔太 | 1 | A | 71 2 | 4 | 2 | 白鳥千鶴子 | 2 | O | 71 3 | 3 | 5 | 田中拓郎 | 1 | A | 70 1 | 3 | 2 | 村松佐知 | 2 | A | 70 (10 rows)
SQLには時系列で処理が進むという考え方がないので、以前のSELECTの結果を使用することができない。
あるSELECTの結果を利用してSQLを実行する場合、SELECTを部分的に埋め込むことになる。
SQLに部分的に埋め込まれたSELECT文を副問い合わせ(サブクエリー)という。
副問い合わせは( )の中にSELECT文を記述する。
結果が1行1列の場合
結果が1行1列の場合、単独の値として扱うことができる。
今回は全体の平均点よりも点数が高い生徒を表示する。
次のSQLをファイルとして作成し実行。(subquery071.sql)
oddtbs=> \i subquery071.sql
gnum | cnum | num | name | gender | blood | score
------+------+-----+------------+--------+-------+-------
1 | 1 | 3 | 北川陽子 | 2 | A | 94
1 | 1 | 5 | 木村葉子 | 2 | AB | 75
1 | 1 | 6 | 藤田智子 | 2 | A | 68
1 | 2 | 1 | 石川大地 | 1 | O | 74
1 | 2 | 4 | 服部圭祐 | 1 | B | 81
1 | 3 | 1 | 瀧下健介 | 1 | B | 82
1 | 3 | 2 | 村松佐知 | 2 | A | 70
...
...
3 | 3 | 4 | 鈴木貴大 | 1 | O | 93
3 | 3 | 5 | 田中拓郎 | 1 | A | 70
3 | 4 | 3 | 文倉翔太 | 1 | A | 71
(35 rows)
結果が1行複数列の場合
結果が1行複数列の場合、例えば行コンストラクタと比較するなどの扱いが必要となる。
今回は担任が'松井'である生徒を表示する。
次のSQLをファイルとして作成し実行。(subquery072.sql)
oddtbs=> \i subquery072.sql
gnum | cnum | num | name | gender | blood | score
------+------+-----+------------+--------+-------+-------
1 | 4 | 1 | 浅原丞 | 1 | O | 69
1 | 4 | 2 | 萩原進 | 1 | A | 62
1 | 4 | 3 | 八木愛実 | 2 | A | 69
1 | 4 | 4 | 鈴木佐知子 | 2 | O | 61
1 | 4 | 5 | 田村洋子 | 2 | AB | 64
1 | 4 | 6 | 岡村ひろ子 | 2 | O | 80
(6 rows)
結果が複数行複数列の場合
結果が複数行複数列の場合、さらに複数の結果と比較できる形式でなければならない。
今回はINを使用する。
担任が'松井'か'森田'である生徒を表示する。
次のSQLをファイルとして作成し実行。(subquery073.sql)
oddtbs=> \i subquery073.sql
gnum | cnum | num | name | gender | blood | score
------+------+-----+------------+--------+-------+-------
1 | 4 | 1 | 浅原丞 | 1 | O | 69
1 | 4 | 2 | 萩原進 | 1 | A | 62
1 | 4 | 3 | 八木愛実 | 2 | A | 69
1 | 4 | 4 | 鈴木佐知子 | 2 | O | 61
1 | 4 | 5 | 田村洋子 | 2 | AB | 64
1 | 4 | 6 | 岡村ひろ子 | 2 | O | 80
3 | 2 | 1 | 石橋直晃 | 1 | A | 58
3 | 2 | 2 | 村上和美 | 2 | A | 91
3 | 2 | 3 | 堀田真理子 | 2 | O | 63
3 | 2 | 4 | 鈴木雄太 | 1 | AB | 45
3 | 2 | 5 | 渡部優子 | 2 | AB | 76
3 | 2 | 6 | 渥美巖 | 1 | AB | 61
(12 rows)
ANY①
副問い合わせの前にANYを指定すると、結果の中に比較演算を成立させる行が存在すればTRUEとなる。
先ほどと同じことはANYを使用しても可能である。
次のSQLをファイルとして作成し実行。(subquery074.sql)
oddtbs=> \i subquery074.sql
結果は前回と同じ
ANY②
ANYを = 以外の演算子と組み合わせる場合は、当然INと同じにはならない。
組ごとの平均点のうちのどれかと比較して点数が高い生徒を表示する。
言い換えると、組ごとの平均点の最低点よりも点数が高いということになる。
次のSQLをファイルとして作成し実行。(subquery075.sql)
oddtbs=> \i subquery075.sql
gnum | cnum | num | name | gender | blood | score
------+------+-----+------------+--------+-------+-------
1 | 1 | 1 | 大石友美 | 2 | O | 63
1 | 1 | 3 | 北川陽子 | 2 | A | 94
1 | 1 | 5 | 木村葉子 | 2 | AB | 75
1 | 1 | 6 | 藤田智子 | 2 | A | 68
1 | 2 | 1 | 石川大地 | 1 | O | 74
1 | 2 | 3 | 片山千春 | 2 | A | 66
1 | 2 | 4 | 服部圭祐 | 1 | B | 81
...
...
3 | 4 | 1 | 増田佳乃 | 2 | O | 57
3 | 4 | 3 | 文倉翔太 | 1 | A | 71
3 | 4 | 6 | 梶間昇平 | 1 | B | 58
(53 rows)
ALL
副問い合わせの前にALLを指定すると、結果の全ての行が演算を成立させる場合のみTRUEとなる。
組ごとの平均点の全てと比較して点数が高い生徒を表示する。
言い換えると、組ごとの平均点の最高点よりも点数が高いということになる。
次のSQLをファイルとして作成して実行。(subquery076.sql)
oddtbs=> \i subquery076.sql
gnum | cnum | num | name | gender | blood | score
------+------+-----+------------+--------+-------+-------
1 | 1 | 3 | 北川陽子 | 2 | A | 94
1 | 2 | 4 | 服部圭祐 | 1 | B | 81
1 | 3 | 1 | 瀧下健介 | 1 | B | 82
2 | 1 | 3 | 片瀬優富子 | 2 | A | 86
2 | 2 | 2 | 正守貴世 | 2 | A | 86
2 | 2 | 3 | 片山マリコ | 2 | A | 81
2 | 2 | 4 | 矢野明恵 | 2 | B | 91
2 | 3 | 5 | 土屋いつ恵 | 2 | A | 89
3 | 1 | 4 | 尾原裕基 | 1 | A | 93
3 | 2 | 2 | 村上和美 | 2 | A | 91
3 | 3 | 1 | 池田綾乃 | 2 | A | 92
3 | 3 | 2 | 西山隆弘 | 1 | O | 91
3 | 3 | 3 | 八木島時史 | 1 | O | 92
3 | 3 | 4 | 鈴木貴大 | 1 | O | 93
(14 rows)
EXISTSやNOT EXISTS演算子によって、あるSELECTの結果が1行でも存在したか否かを確認できる。
EXISTSは存在した場合、NOT EXISTSは存在しなかった場合にTRUEとなる。
EXISTS、NOT EXISTSを使用したSQLも一種の副問い合わせである。
EXISTS(SELECT文) NOT EXISTS(SELECT文)
基本的な例(ここはデータのみの表示)
oddtbs=> \t Showing only tuples. oddtbs=> select exists(select * from student where score >= 90); t oddtbs=> select not exists(select * from student where score >= 90); f oddtbs=> select exists(select * from student where score < 40); f oddtbs=> select not exists(select * from student where score < 40); t oddtbs=> \t Tuples only is off.
応用例(相関副問い合わせ)
全員の点数が50点以上だったクラスを選択して表示する。
次のSQLをファイルとして作成し実行。(exists071.sql)
oddtbs=> \i exists071.sql
gnum | num | charge
------+-----+--------
1 | 2 | 佐藤
1 | 3 | 鈴木
1 | 4 | 松井
2 | 1 | 岡田
2 | 2 | 山本
(5 rows)
※ このように外のSQLで使用しているテーブルを副問い合わせでも使用している場合、相関副問い合わせという。
学年テーブル(grade)、組テーブル(class)、生徒テーブル(student)の3つを結合したビューを作成する。
次のSQLをファイルとして作成。(student_view071.sql)
ログイン画面から実行。
oddtbs=> \i student_view071.sql
...
確認。
oddtbs=> select * from student_v;
gnum | color | cnum | charge | num | name | gender | blood | score
------+-------+------+--------+-----+--------------+--------+-------+-------
1 | 青 | 1 | 田中 | 1 | 大石友美 | 2 | O | 63
1 | 青 | 1 | 田中 | 2 | 中村優作 | 1 | O | 48
1 | 青 | 1 | 田中 | 3 | 北川陽子 | 2 | A | 94
1 | 青 | 1 | 田中 | 4 | 望月慎太郎 | 1 | A | 53
1 | 青 | 1 | 田中 | 5 | 木村葉子 | 2 | AB | 75
1 | 青 | 1 | 田中 | 6 | 藤田智子 | 2 | A | 68
1 | 青 | 2 | 佐藤 | 1 | 石川大地 | 1 | O | 74
...
...
3 | 緑 | 4 | 島田 | 4 | 鷲山綾子 | 2 | B | 45
3 | 緑 | 4 | 島田 | 5 | 内山絢平 | 1 | AB | 54
3 | 緑 | 4 | 島田 | 6 | 梶間昇平 | 1 | B | 58
(72 rows)