SlideShare a Scribd company logo
1 of 81
Download to read offline
1
SQL講座
概要
• SQLの基礎構文と現場で使用できるテクニックを学習します。
2
目次
• SQL
• GROUP BY
• DISTINCT
• 結合(クロス結合、内部結合、外部結合)
• 並び替え(ORDER BY)
• サブクエリ
• CASE文
• 演習問題
• SQLの速度
3
前提条件
• このテキストの内容はPostgreSQL(バージョン9.6.9)の環境で検証し
たものとなっています。
• テキストと同じ環境で検証する場合はPostgreSQLをインストールし、
事前にデータベース(axizdb)とユーザー(axizuser)を作成してくだ
さい。
• また、テキストの例では分かりやすさを優先して、テーブル名やカ
ラム名に日本語を使用しています。
※実際のプロジェクトではテーブル名やカラム名に日本語を使うこと
は推奨しません。
4
SQL
5
GROUP BY
• GROUP BY
• GROUP BY は複数のレコードを1行にまとめる場合に使用します。
• 集約関数(COUNT, SUM, MAX, MIN, AVGなど)と組み合わせて使用する場合が
多いです。
• 集約関数の結果に対して絞り込み条件を指定する場合は、HAVING句を使用し
ます。
6
-- 例
SELECT column1, SUM(column2), COUNT(*)
FROM table1
GROUP BY column1
HAVING SUM(column2) > 10000;
GROUP BY
• GROUP BY
• 集約関数を適用しないカラムで絞り込みを行う場合、WHERE句で絞り込む方
法とHAVING句で絞り込む方法があります。
• 結果は同じになりますが、パフォーマンスに差が出る場合があります。
7
-- 例①
SELECT column1, SUM(column2)
FROM table1
WHERE column1 = 200
GROUP BY column1 ;
-- 例②
SELECT column1, SUM(column2)
FROM table1
GROUP BY column1
HAVING column1 = 200;
GROUP BY
• COUNT関数(例題)
• COUNTは集約したレコードの件数を取得する際に使用します。
8
どのようなSQL文で実現できるか。
SQL文を作成してみましょう。
COUNT
商品名 件数
商品A 3
商品B 2
商品C 5
売上_GROUP
売上日 商品名 単価 数量
2018/9/1 商品A 300 10
2018/9/2 商品A 300 5
2018/9/3 商品A 300 20
2018/9/4 商品B 400 8
2018/9/5 商品B 400 5
2018/9/6 商品C 500 5
2018/9/7 商品C 500 10
2018/9/8 商品C 500 8
2018/9/9 商品C 500 7
2018/9/10 商品C 500 10
GROUP BY
• COUNT関数(解答)
• COUNTは集約したレコードの件数を取得する際に使用します。
9
-- 商品ごとのレコード件数を取得
SELECT 商品名, COUNT(*) 件数
FROM 売上_GROUP
GROUP BY 商品名;
COUNT
商品名 件数
商品A 3
商品B 2
商品C 5
売上_GROUP
売上日 商品名 単価 数量
2018/9/1 商品A 300 10
2018/9/2 商品A 300 5
2018/9/3 商品A 300 20
2018/9/4 商品B 400 8
2018/9/5 商品B 400 5
2018/9/6 商品C 500 5
2018/9/7 商品C 500 10
2018/9/8 商品C 500 8
2018/9/9 商品C 500 7
2018/9/10 商品C 500 10
GROUP BY
• SUM関数
• SUMは数値の合計を求めるときに使用します。
10
-- 商品ごとの数量と金額の合計を取得
SELECT 商品名, SUM(数量) 数量合計, SUM(単価 * 数量) 金額
FROM 売上_GROUP
GROUP BY 商品名;
SUM
商品名 数量合計 金額
商品A 35 10500
商品B 13 5200
商品C 40 20000
売上_GROUP
売上日 商品名 単価 数量
2018/9/1 商品A 300 10
2018/9/2 商品A 300 5
2018/9/3 商品A 300 20
2018/9/4 商品B 400 8
2018/9/5 商品B 400 5
2018/9/6 商品C 500 5
2018/9/7 商品C 500 10
2018/9/8 商品C 500 8
2018/9/9 商品C 500 7
2018/9/10 商品C 500 10
GROUP BY
• MAX関数, MIN関数
• MAXは最大値を、MINは最小値を求めます。
11
-- 商品ごとの数量と金額の合計を取得
SELECT 商品名, MAX(数量) 最大売上数量
, MIN(数量) 最小売上数量, MAX(売上日) 最新売上日
FROM 売上_GROUP
GROUP BY 商品名;
MAX, MIN
商品名 最大売上数量 最小売上数量 最新売上日
商品A 20 5 2018/9/3
商品B 8 5 2018/9/5
商品C 10 5 2018/9/9
売上_GROUP
売上日 商品名 単価 数量
2018/9/1 商品A 300 10
2018/9/2 商品A 300 5
2018/9/3 商品A 300 20
2018/9/4 商品B 400 8
2018/9/5 商品B 400 5
2018/9/6 商品C 500 5
2018/9/7 商品C 500 10
2018/9/8 商品C 500 8
2018/9/9 商品C 500 7
2018/9/10 商品C 500 10
DISTINCT
• DISTINCT
• SELECT句に記述したカラムの組み合わせを重複を排除した形で取得すること
ができます。
12
-- 書き方
SELECT DISTINCT column1, column2, …
FROM table1
DISTINCT
• DISTINCT(例題)
13
売上_DISTINCT
売上日 顧客名 商品名 数量 金額
2018/9/1 顧客A 商品① 10 1000
2018/9/1 顧客B 商品① 20 4000
2018/9/2 顧客A 商品③ 10 3000
2018/9/2 顧客B 商品① 5 500
2018/9/2 顧客C 商品③ 5 1500
2018/9/3 顧客C 商品③ 2 600
2018/9/4 顧客A 商品① 5 500
2018/9/4 顧客B 商品② 10 2000
2018/9/5 顧客A 商品② 3 600
顧客名 商品名
顧客A 商品①
顧客A 商品②
顧客A 商品③
顧客B 商品①
顧客B 商品②
顧客C 商品③
どのようなSQL文で実現できるか。
SQL文を作成してみましょう。
DISTINCT
• DISTINCT(解答)
14
-- 顧客と商品の組み合わせを取得
SELECT DISTINCT 顧客名, 商品名
FROM 売上_DISTINCT;
売上_DISTINCT
売上日 顧客名 商品名 数量 金額
2018/9/1 顧客A 商品① 10 1000
2018/9/1 顧客B 商品① 20 4000
2018/9/2 顧客A 商品③ 10 3000
2018/9/2 顧客B 商品① 5 500
2018/9/2 顧客C 商品③ 5 1500
2018/9/3 顧客C 商品③ 2 600
2018/9/4 顧客A 商品① 5 500
2018/9/4 顧客B 商品② 10 2000
2018/9/5 顧客A 商品② 3 600
顧客名 商品名
顧客A 商品①
顧客A 商品②
顧客A 商品③
顧客B 商品①
顧客B 商品②
顧客C 商品③
結合
• 結合の種類
結合にはいくつかの種類があります。
具体的には
• クロス結合
• 内部結合
• 外部結合
• 自己結合
• 自然結合
などがあります。
15
クロス結合
• クロス結合
• 結合対象となるテーブルのレコードの全ての組み合わせを取得する結
合方法です。
• 2通りの書き方があります。
• 取得するレコード数は Aのレコード数 × Bのレコード数
• ②の書き方の場合、内部結合をしようとして、結合条件を記述し忘れ
た際に意図せずクロス結合になってしまうことがあるので注意が必要
です。
16
-- 書き方①
SELECT * FROM table1
CROSS JOIN table2
-- 書き方②
SELECT * FROM table1, table2
クロス結合
• クロス結合(例)
17
クロス結合
SELECT * FROM プログラム言語
CROSS JOIN DBMS;
結合結果のレコード数は
3×3 = 9レコード となる。
プログラム名 DB名
PHP Oracle
PHP MySQL
PHP PostgreSQL
Java Oracle
Java MySQL
Java PostgreSQL
Ruby Oracle
Ruby MySQL
Ruby PostgreSQL
プログラム言語
プログラム名
PHP
Java
Ruby
DBMS
DB名
Oracle
MySQL
PostgreSQL
クロス結合
• クロス結合は通常は使用しない
• クロス結合は、対象となるレコード同士のすべての組み合わせを取得
するため、パフォーマンスが低下します。
• これを使用しなければ実現できない、という場合以外はシステムのプ
ログラム内で使用してはいけません。
18
内部結合
• 内部結合
• 結合条件を指定し、合致するレコードのみを取得する結合方法です。
• 2通りの書き方があります。
• お勧めは①の書き方。
• ②の書き方の場合、絞り込み条件なのか結合条件なのかが分かりにくくなり
ます。また、結合条件を書き忘れてもエラーにならず、意図せずクロス結合
が行われてしまいます。
19
-- 書き方①
SELECT * FROM table1 t1
INNER JOIN table2 t2
ON t1.column = t2.column
-- 書き方②
SELECT * FROM table1 t1, table2 t2
WHERE t1.column = t2.column
内部結合
• 内部結合(例題)
20
内部結合
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
商品単価_結合用
id 単価
1 100
2 160
3 80
7 300
8 200
9 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
どのようなSQL文で実現できるか。
SQL文を作成してみましょう。
内部結合
• 内部結合(解答)
21
idをキーとした内部結合
idが一致するレコードのみが抽出される
SELECT 商品.id, 商品名, 単価
FROM 商品_結合用 商品
INNER JOIN 商品単価_結合用 商品単価
ON 商品.id = 商品単価.id
内部結合
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
商品単価_結合用
id 単価
1 100
2 160
3 80
7 300
8 200
9 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
外部結合
• 外部結合
• 外部結合は3つの種類があります。
• 左外部結合、右外部結合、全外部結合、の3つです。
• 左外部結合と右外部結合は、実質的に同じです。
• 全外部結合はDBMSによってはサポートされていないので注意が必要で
す。
22
-- 書き方(左外部結合)
SELECT * FROM table1 t1
LEFT OUTER JOIN table2 t2
ON t1.column = t2.column
-- 書き方(右外部結合)
SELECT * FROM table1 t1
RIGHT OUTER JOIN table2 t2
ON t1.column = t2.column
-- 書き方(全外部結合)
SELECT * FROM table1 t1
FULL OUTER JOIN table2 t2
ON t1.column = t2.column
外部結合
• 左外部結合(例)
23
SELECT 商品.id, 商品名, 単価
FROM 商品_結合用 商品
LEFT OUTER JOIN 商品単価_結合用 商品単価
ON 商品.id = 商品単価.id
左外部結合
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
商品単価_結合用
id 単価
1 100
2 160
3 80
7 300
8 200
9 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう (NULL)
5 いちご (NULL)
6 メロン (NULL)
外部結合
• 右外部結合(例)
24
SELECT 商品単価.id, 商品名, 単価
FROM 商品_結合用 商品
RIGHT OUTER JOIN 商品単価_結合用 商品単価
ON 商品.id = 商品単価.id
右外部結合
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
商品単価_結合用
id 単価
1 100
2 160
3 80
7 300
8 200
9 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
7 (NULL) 300
8 (NULL) 200
9 (NULL) 600
外部結合
• 全外部結合(例)
25
SELECT 商品.id id1, 商品単価.id id2, 商品名, 単価
FROM 商品_結合用 商品
FULL OUTER JOIN 商品単価_結合用 商品単価
ON 商品.id = 商品単価.id
全外部結合
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
商品単価_結合用
id 単価
1 100
2 160
3 80
7 300
8 200
9 600
id1 id2 商品名 単価
1 1 りんご 100
2 2 バナナ 160
3 3 オレンジ 80
4 (NULL) ぶどう (NULL)
5 (NULL) いちご (NULL)
6 (NULL) メロン (NULL)
(NULL) 7 (NULL) 300
(NULL) 8 (NULL) 200
(NULL) 9 (NULL) 600
内部結合と外部結合
• 内部結合と外部結合の比較
26
内部結合
結合対象
左外部結合
商品単価
id 値段
1 100
2 160
3 80
7 300
8 200
9 600
商品_結合用
id 商品名
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう (NULL)
5 いちご (NULL)
6 メロン (NULL)
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
内部結合と外部結合
• 内部結合と外部結合の名前の由来
27
クロス結合
内部結合
外部結合
集合で考えた時、
内部結合で抽出されたレコードはク
ロス結合の集合に含まれます。
外部結合では、クロス結合の集合に
含まれないレコードが抽出されるこ
とがあります(NULLを含む場合)。
クロス結合の集合の内部か外部かで、
内部結合と外部結合という名前に
なっています。
外部結合
• 外部結合のまとめ
• 外部結合をする場合は左外部結合を使用する。(一般的に左の方が見
やすいため)
• 外部結合をする際に結合元となるテーブルはマスタのテーブルを選択
する。
28
結合の種類
• 自己結合
• 自分自身のテーブルと結合する結合。
• 結合対象のテーブルが自分自身のテーブルになっただけで、結合の方
法は内部結合と同じです。
29
-- 自己結合
SELECT * FROM table1 t1
INNER JOIN table1 t1
ON t1.column = t1.column
結合の種類
• 自然結合
• 結合条件を記述せず、テーブルの同じ名前の列名同士で統合が結ばれ
る結合
• 内部結合よりも記述が短くなりますが、どのカラムで結合しているか
はテーブル定義を理解している必要があるため、あえて自然結合で記
述するメリットはほとんどないでしょう。
30
-- 書き方
SELECT * FROM table1
NATURAL JOIN table2
-- 内部結合での表現
SELECT * FROM table1
INNER JOIN table2
ON table1.id = table2.id
結合
• 結合全体のまとめ
• 通常の業務で多く使用するのは内部結合と左外部結合。
• 読みやすい書き方で記述する。
• DBMSによってはここで紹介した結合のSQLでサポートされていない
DBMSもある。また、SQLの実装が異なる場合もあるので注意する。
31
集合演算
• SQLの集合演算
• 和集合(UNION)
• 差集合(EXCEPT)
• 積集合(INTERSECT)
32
UNION
• UNIONとUNION ALL
• 3つのSELECT文の和集合の結果を得るための演算子。
• UNION と UNION ALL の違いは、SELECT文①とSELECT文②に重複があっ
た場合に現れる。
• UNIONは、重複はまとめて表示する。UNION ALL は、重複もそのまま
表示する。
• パフォーマンス的にはUNION ALLの方が速い。UNIONは、重複排除のた
めにソートを行うが、UNION ALLではソートを行わないため。
33
-- 書き方
SELECT文①
UNION
SELECT文②
-- 書き方
SELECT文①
UNION ALL
SELECT文②
UNION
• UNION(例)
34
同じレコードが除外されて表示される。
SELECT * FROM A店商品
UNION
SELECT * FROM B店商品
A店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう 300
5 いちご 200
B店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 90
6 メロン 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
3 オレンジ 90
4 ぶどう 300
5 いちご 200
6 メロン 600
UNION
• UNION ALL(例)
35
同じレコードも表示される。
SELECT * FROM A店商品
UNION ALL
SELECT * FROM B店商品
A店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう 300
5 いちご 200
B店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 90
6 メロン 600
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう 300
5 いちご 200
1 りんご 100
2 バナナ 160
3 オレンジ 90
6 メロン 600
EXCEPT
• EXCEPT
• UNIONの逆で、差集合を求めるための演算子。
• SELECT文①の結果から下のSELECT文②の結果を除いた結果が取得でき
る。
• Oracleの場合はMINUS演算子がEXCEPTの役割を果たします。
36
-- 書き方
SELECT文①
EXCEPT
SELECT文②
EXCEPT
• EXCEPT(例)
37
重複しているリンゴとバナナは
1行のみ表示される
SELECT * FROM A店商品
EXCEPT
SELECT * FROM B店商品
A店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう 300
5 いちご 200
B店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 90
6 メロン 600
id 商品名 単価
3 オレンジ 80
4 ぶどう 300
5 いちご 200
INTERSECT
• INTERSECT
• 2つのSELECT文の積(共通部分)を求めるための演算子。
• SELECT文①とSELECT文②に共通するレコードが取得できる。
38
-- 書き方
SELECT文①
INTERSECT
SELECT文②
INTERSECT
• INTERSECT (例)
39
product_shop1とproduct_shop2の共
通している行が表示される。
SELECT * FROM A店商品
INTERSECT
SELECT * FROM B店商品
A店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう 300
5 いちご 200
B店商品
id 商品名 単価
1 りんご 100
2 バナナ 160
3 オレンジ 90
6 メロン 600
id 商品名 単価
1 りんご 100
2 バナナ 160
並び替え
• ORDER BY
• SELECT文を実行した際の結果の並び順を指定したい場合にはORDER BY
句を指定します。
• 並び替えの基準となるカラムを指定し、昇順の場合はASC, 降順の場合
はDESCを指定します。省略した場合は昇順となります。
• カラムは複数指定することも可能です。その場合、優先順位の高いも
のから順に記述していきます。
40
-- 書き方
SELECT句
FROM句
WHERE句
ORDER BY column1 (ASC|DESC), column2 (ASC|DESC),…
並び替え
• ORDER BY(例題)
41
売上_並び替え用
売上日 商品名 単価 数量
2018/9/1 商品A 100 15
2018/9/3 商品C 300 7
2018/9/2 商品A 100 20
2018/9/2 商品B 200 12
2018/9/4 商品B 200 5
売上日 商品名 単価 数量 金額
2018/9/2 商品B 200 12 2400
2018/9/3 商品C 300 7 2100
2018/9/2 商品A 100 20 2000
2018/9/1 商品A 100 15 1500
2018/9/4 商品B 200 5 1000
どのようなSQL文で実現できるか。
SQL文を作成してみましょう。
並び替え
• ORDER BY(解答)
42
-- 金額の降順で並べる
SELECT * , 単価 * 数量 AS 金額
FROM 売上_並び替え用
ORDER BY 単価 * 数量 DESC
売上_並び替え用
売上日 商品名 単価 数量
2018/9/1 商品A 100 15
2018/9/3 商品C 300 7
2018/9/2 商品A 100 20
2018/9/2 商品B 200 12
2018/9/4 商品B 200 5
売上日 商品名 単価 数量 金額
2018/9/2 商品B 200 12 2400
2018/9/3 商品C 300 7 2100
2018/9/2 商品A 100 20 2000
2018/9/1 商品A 100 15 1500
2018/9/4 商品B 200 5 1000
サブクエリ
• サブクエリ
• 副問い合わせとも呼ばれます。
• SELECT文の結果を別のクエリ(SQL文)に使用する書き方。
• FROM句として使用したり、結合対象としてサブクエリを使用するこ
とも多いです。
• 更新系のSQLでも使用することができます。
43
-- 例(SELECT文の結果をJOINの対象にする)
SELECT table1.* , total
FROM table1
INNER JOIN (SELECT id, SUM(num) total
FROM table2 GROUP BY id) t2
ON table1.id = t2.id
サブクエリ
• サブクエリ(例)
44
-- 例(販売数を商品で集約した結果を、結合に使用する)
SELECT 商品.*, 売上数量
FROM 商品_サブクエリ用 商品
LEFT OUTER JOIN (SELECT 商品id, SUM(数量) 売上数量
FROM 売上_サブクエリ用
GROUP BY 商品id) 売上
ON 商品.商品id = 売上.商品id
商品_サブクエリ用
商品id 商品名 単価
001 商品A 200
002 商品B 350
003 商品C 170
004 商品D 200
005 商品E 300
売上_サブクエリ用
売上日付 商品id 数量
2018/9/1 001 20
2018/9/2 001 15
2018/9/3 002 40
2018/9/4 002 30
2018/9/5 003 50
商品id 商品名 単価 売上数量
004 商品D 200 (NULL)
002 商品B 350 70
001 商品A 200 35
003 商品C 170 50
005 商品E 300 (NULL)
サブクエリ
• 相関サブクエリ
• 外側のクエリの値を内側のクエリ内で使用するサブクエリ
• よく使用されるのはEXISTSを使用したSQL文
45
-- 例(table2に、idが一致するレコードが存在するtable1のレコードを表示)
SELECT * FROM table1 t1
WHERE EXISTS (SELECT * FROM table2 t2
WHERE t1.id = t2.id)
サブクエリ
• 相関サブクエリ(例)
46
-- 9/1~9/3の期間に一度でも販売された商品を取得するSQL文
SELECT * FROM 商品_サブクエリ用 商品
WHERE EXISTS (SELECT * FROM 売上_サブクエリ用
WHERE 商品id = 商品.商品id
AND 売上日付 BETWEEN '2018/9/1' AND '2018/9/3')
商品id 商品名 単価
001 商品A 200
002 商品B 350
商品_サブクエリ用
商品id 商品名 単価
001 商品A 200
002 商品B 350
003 商品C 170
004 商品D 200
005 商品E 300
売上_サブクエリ用
売上日付 商品id 数量
2018/9/1 001 20
2018/9/2 001 15
2018/9/3 002 40
2018/9/4 002 30
2018/9/5 003 50
サブクエリ
• スカラ・サブクエリ
• SELECT句の中にサブクエリを記述する方法。
• 結果がイメージしやすいが、多用するとパフォーマンスが悪くなる。
47
-- SELECT句の中で、別のテーブルのレコードを取得する
SELECT id
, (SELECT name
FROM table2
WHERE id = table1.id) エイリアス名
FROM table1
サブクエリ
• スカラ・サブクエリ(例)
48
-- 売上のレコードを取得して、商品名も表示する
SELECT 売上日付
, 商品id
, (SELECT 商品名 FROM 商品_サブクエリ用
WHERE 商品id = 売上.商品id) 商品名
, 数量
FROM 売上_サブクエリ用 売上
売上日付 商品id 商品名 数量
2018/9/4 002 商品B 30
2018/9/1 001 商品A 20
2018/9/3 002 商品B 40
2018/9/2 001 商品A 15
2018/9/5 003 商品C 50
売上_サブクエリ用
売上日付 商品id 数量
2018/9/1 001 20
2018/9/2 001 15
2018/9/3 002 40
2018/9/4 002 30
2018/9/5 003 50
商品_サブクエリ用
商品id 商品名 単価
001 商品A 200
002 商品B 350
003 商品C 170
004 商品D 200
005 商品E 300
CASE式
• CASE式
• SQLで条件分岐をするための構文
• SELECT句、WHERE句、GROUP BY句のなど、どこでも使用可能。
• 一般的にはWHERE句では使用しない。SELECT句の中で使用する。
• maxや、sumなどの集約関数の中に入れ込むこともある。
49
-- 書き方
SELECT
CASE
WHEN 条件式1 THEN 値1
WHEN 条件式2 THEN 値2
ELSE 値3
END エイリアス名
FROM table2
CASE式
• CASE式(例題)
50
商品_CASE用
商品id 商品名 単価
001 商品A 1000
002 商品B 5000
003 商品C 10000
商品id 商品名 単価 ランク
001 商品A 1000 安物
002 商品B 5000 普通
003 商品C 10000 高級品
どのようなSQL文で実現できるか。
SQL文を作成してみましょう。
CASE式
• CASE式(解答)
51
-- 単価によってランクを決める
SELECT *
, CASE
WHEN 単価 >= 10000 THEN '高級品'
WHEN 単価 BETWEEN 5000 AND 9999 THEN '普通'
ELSE '安物'
END ランク
FROM 商品_CASE用
商品_CASE用
商品id 商品名 単価
001 商品A 1000
002 商品B 5000
003 商品C 10000
商品id 商品名 単価 ランク
001 商品A 1000 安物
002 商品B 5000 普通
003 商品C 10000 高級品
ウィンドウ関数
• ウィンドウ関数
• GROUP BY を使わずとも集約関数の結果を取得できる関数。
• row_number, count, sum, max, rank, dense_rank などがあります。
• 使いこなせると非常に便利ですが、DBMSによっては実装されておらず、
使用できないものもあるので注意が必要です。
• 関数名() over(…) のように使用します。overの中にはpartition by句と
order by句が記述できます。
52
-- 例
SELECT
row_number() over(partition by column1 order by column2)
, count() over(partition by column3 order by column4)
FROM table1
ウィンドウ関数
• ウィンドウ関数(例)
53
--例(売上の分析)
select
row_number() over(order by 売上日付, 顧客, 商品) 連番
, rank() over(order by 単価 * 数量 desc) 売上ランク
, sum(単価 * 数量) over(partition by 売上日付 order by 商品) 累計
, sum(単価 * 数量) over(partition by 売上日付) 日付合計
from 売上_ウィンドウ関数用
連番 売上ランク 累計 日付合計
1 3 20000 40000
2 4 35000 40000
3 6 40000 40000
4 5 8000 53000
5 1 53000 53000
6 2 40000 40000
売上_ウィンドウ関数用
売上日付 顧客 商品 単価 数量
2018/9/1 X商店 商品A 200 100
2018/9/1 X商店 商品B 300 50
2018/9/1 X商店 商品C 500 10
2018/9/2 Y商店 商品A 200 40
2018/9/2 Y商店 商品B 300 150
2018/9/3 Z商店 商品C 500 80
SQLまとめ
• SQLまとめ
• 結合、サブクエリの使い方に慣れておきましょう。
• CASE式は非常に便利です。有効に使っていきましょう。
※やりすぎると読みづらいSQL文になって、メンテが難しくなることも
あるので注意しましょう。
54
演習問題
55
演習問題
• 演習問題
• 事前準備:以下のテーブルを作成しておいてください。
• 商品カテゴリ(category)
• 商品(products)
• 顧客(customer)
• 仕入先(supplier)
• 販売(sales)
• 購買(purchases)
• 商品_複数(products_munlti)
56
演習問題
• 演習問題
57
商品カテゴリ category
論理名 物理名 型 primary key
商品カテゴリID category_id integer 〇
商品カテゴリ名 category_name varchar(50)
商品 products
論理名 物理名 型 primary key
商品ID products_id integer 〇
商品名 products_name varchar(50)
商品カテゴリID category_id integer
仕入単価 p_price real
販売単価 s_price real
演習問題
• 演習問題
58
顧客 customer
論理名 物理名 型 primary key
顧客ID customer_id integer 〇
顧客名 customer_name varchar(50)
仕入先 supplier
論理名 物理名 型 primary key
仕入先ID supplier_id integer 〇
仕入先名 supplier_name varchar(50)
演習問題
• 演習問題
59
販売 sales
論理名 物理名 型 primary key
販売ID sales_id integer 〇
顧客ID customer_id integer
販売日付 sales_date date
商品ID products_id integer
販売数量 unit_sales real
購買 purchases
論理名 物理名 型 primary key
購入ID purchases_id integer 〇
仕入先ID supplier_id integer
購入日付 purchases_date date
商品ID products_id integer
購入数量 unit_purchases real
演習問題
• 演習問題①
• 一度でも販売されたことのある商品(salesにデータがある)を取得する
SQL文を作成してください。
• 対象テーブル商品(products), 販売(sales)
60
products_id products_name category_id p_price s_price
1 りんご 1 100 120
2 みかん 1 120 150
4 ボールペン 2 260 300
6 電池 2 370 400
7 コップ 3 600 700
8 椅子 3 1700 2000
9 地球儀 3 4100 5000
期待する結果
演習問題
• 演習問題②
• 一度も販売されていない商品(salesにデータがない)を検索するSQL文を
作成してください。
• 対象テーブル:商品(products), 販売(sales)
61
products_id products_name category_id p_price s_price
3 バナナ 1 240 300
5 ティッシュ 2 180 250
期待する結果
演習問題
• 演習問題③
• 月単位の売上合計金額を取得するSQL文を作成してください。
• 対象テーブル:商品(products), 販売(sales)
62
売上月 売上金額
2018-07 20410
2018-08 13200
2018-09 20600
期待する結果
演習問題
• 演習問題④
• 商品を単価の値によって分類し、その商品が何アイテムあるかをカウ
ントするSQL文を作成してください。
• 対象テーブル:商品(products)
63
ランク count
0~300 5
1000~ 2
300~1000 2
期待する結果
演習問題
• 演習問題⑤
• 商品カテゴリを1レコードにまとめて取得するSQL文を作成してくださ
い。
• 対象テーブル:商品カテゴリ(category)
64
カテゴリ名
食品
日用品
雑貨
カテゴリ1 カテゴリ2 カテゴリ3
食品 日用品 雑貨
期待する結果
演習問題
• 演習問題⑥
• 月単位で、カテゴリ別の売上合計金額を取得するSQL文を作成してく
ださい。
• 対象テーブル:販売(sales), 商品(products)商品
65
売上月 食品売上 日用品売上 雑貨売上
2018-07 6810 4400 9000
2018-08 3600 0 9600
2018-09 2700 2900 15000
期待する結果
演習問題
• 演習問題⑦
• 仕入と売上を同時に取得するSQL文を作成してください。
• 並び順は取引日付の昇順とする。
• 対象テーブル:販売(sales), 購買(purchases), 商品(products)
66
取引名 取引日付 商品名 数量
仕入 2018/7/1 ボールペン 50
仕入 2018/7/1 コップ 50
仕入 2018/7/1 バナナ 50
仕入 2018/7/1 椅子 50
仕入 2018/7/1 ティッシュ 50
仕入 2018/7/1 りんご 50
仕入 2018/7/1 地球儀 50
仕入 2018/7/1 電池 50
売上 2018/7/1 りんご 7
仕入 2018/7/1 みかん 50
売上 2018/7/4 みかん 12
売上 2018/7/5 ボールペン 4
売上 2018/7/5 りんご 11
期待する結果
演習問題
• 演習問題⑧
• 商品ごとの在庫数(仕入数 – 売上数)を取得するSQLを作成してくだ
さい。
• 対象テーブル:販売(sales), 購買(purchases), 商品(products)
67
商品名 在庫数
りんご 12
みかん -7
バナナ 50
ボールペン 29
ティッシュ 50
電池 47
コップ 42
椅子 43
地球儀 49
期待する結果
演習問題
• 演習問題⑨
• 1レコードに複数の情報を持つテーブルに対して
• 以下のように、複数のレコードに分けて取得できるようなSQL文を作
成してください。
• 対象テーブル:商品_複数(products_multi)
68
id1 name1 price1 id2 name2 price2 id3 name3 price3
1 リング 100 2 みかん 200 3 バナナ 300
id name price
1 リンゴ 100
2 みかん 200
3 バナナ 300
期待する結果
演習問題
• 演習問題⑩
• products(商品)をs_price(販売単価)の安い順にランク付けするSQL文を作
成してください。
• 対象テーブル:商品(products)
69
商品名 値段 ランク
りんご 120 1
みかん 150 2
ティッシュ 250 3
バナナ 300 4
ボールペン 300 4
電池 400 6
コップ 700 7
椅子 2000 8
地球儀 5000 9
期待する結果
演習問題
• 演習問題⑪
• 顧客・日付単位で、購売上金額のランキングを出力するSQLを作成し
てください。
• 対象テーブル:販売(sales), 商品(products), 顧客(customer)
70
顧客名 売上日付 商品名 売上金額 ランク
川上商店 2018/7/19 地球儀 4100 1
川上商店 2018/8/20 椅子 3400 2
川上商店 2018/7/15 椅子 3400 2
川上商店 2018/8/10 みかん 2400 4
川上商店 2018/9/3 ボールペン 1820 5
川上商店 2018/7/20 りんご 1500 6
川上商店 2018/7/4 みかん 1440 7
川上商店 2018/7/5 ボールペン 1040 8
川上商店 2018/7/1 りんご 700 9
川上商店 2018/7/9 電池 370 10
中山商事 2018/9/5 椅子 8500 1
中山商事 2018/8/15 コップ 4800 2
中山商事 2018/9/3 地球儀 4100 3
中山商事 2018/7/25 ボールペン 2600 4
期待する結果
演習問題
• 演習問題⑫
• 商品テーブル(products)から、商品の組み合わせを出力するSQLを作成
してください。(図は一部抜粋)
• 対象テーブル:商品(products)
71
商品名1 商品名2
みかん りんご
バナナ りんご
バナナ みかん
ボールペン りんご
ボールペン みかん
ボールペン バナナ
ティッシュ りんご
ティッシュ みかん
ティッシュ バナナ
ティッシュ ボールペン
期待する結果
演習問題
• 演習問題⑬
• 販売テーブル(sales)から、商品ごとの販売日が一番古いデータを出力
するSQLを作成してください。
• 対象テーブル:商品(products), 販売(sales)
72
商品名 売上日付
りんご 2018/7/1
みかん 2018/7/4
ボールペン 2018/7/5
電池 2018/7/9
コップ 2018/8/15
椅子 2018/7/15
地球儀 2018/7/19
期待する結果
SQLの速度
73
SQLの速度
• SQLの速度
• SQLは同一の結果を得るにも複数の書き方ができる場合があります。
• 複数の書き方が存在する場合にどちらの方がパフォーマンスが優れて
いるかを学習していきます。
74
SQLの速度
• INとEXISTS
• サブクエリで条件指定してレコードを取得する場合、INによる書き方
とEXISTSによる書き方があります。
• 下の2つの書き方は同じ結果になります。どちらがパフォーマンス的
にすぐれているでしょうか。
75
-- EXISTSの場合
SELECT *
FROM products p
WHERE EXISTS (SELECT * FROM sales
WHERE products_id = p.products_id);
-- INの場合
SELECT *
FROM products p
WHERE products_id IN (SELECT products_id FROM sales);
SQLの速度
• INよりもEXISTS
• INとEXISTSの場合、一般的にEXISTSの方が優れています。
• INの場合は、先にサブクエリを実行して、その結果に対して外側のク
エリを実行します。
• EXISTSの場合は、外側のクエリ1件1件に対してサブクエリを実行しま
すが、結合キーにインデックスが張られていれば、1回のアクセスで
済むため、パフォーマンスは良くなります。
• ただし、実際には実行計画を比較してみないとどちらが優れているか
の確証は得られません。どちらも同じ実行計画になる場合もあります。
76
SQLの速度
• 結合+DISTINCTとEXISTS
• INやEXISTSと同じ結果を得るために、結合を用いることもできます。
• ただし結合を使用する場合は、結果を一意にするためにDISTINCTが必
要な場面もあります。
77
-- EXISTSの場合
SELECT *
FROM products p
WHERE EXISTS (SELECT * FROM sales
WHERE products_id = p.products_id)
-- 結合の場合
SELECT DISTINCT p.*
FROM products p
INNER JOIN sales s
ON p.products_id = s.products_id
SQLの速度
• 結合+DISTINCTよりもEXISTS
• このような場合、EXISTSの方が高速になります。
• 理由はDISTINCTは重複排除のためにソートをするため、その分のコス
トがかかります。
• DISTINCTを使用しない場合は、結合とEXISTSでどちらの方が速いかは
ケースバイケースです。
78
SQLの速度
• UNIONとUNION ALL
• UNIONとUNION ALL では、UNION ALLの方が高速です。
• 理由は、UNIONは重複削除のためにソートの処理を行うためです。
• そのため、重複がないことが分かっている場合や、ソートの必要がな
い場合はUNION ALLを使用することにしましょう。
79
SQLの速度
• HAVINGとWHERE
• GROUP BY句を使用する場合、HAVING句とWHERE句による絞り込みが可
能です。例えば以下の2つのSQL文は同じ結果になります。
80
-- HAVINGの場合
SELECT category_id, COUNT(*), MAX(products_id), MIN(products_id)
FROM products_2
GROUP BY category_id
HAVING category_id = 3
-- WHEREの場合
SELECT category_id, COUNT(*), MAX(products_id), MIN(products_id)
FROM products_2
WHERE category_id = 3
GROUP BY category_id
SQLの速度
• HAVINGよりもWHERE
• この場合はWHERE句で絞り込みをした方が高速になります。
• 理由は、WHERE句であらかじめ絞り込んでおけば、GROUP BYで集約す
る際のコストを抑えることができるためです。
• SUMやCOUNTの結果に対しての条件指定はHAVINGでしかできませんが、
WHEREでも絞り込める場合はWHEREで絞り込むようにしましょう。
81

More Related Content

More from keki3

Computer terminology
Computer terminologyComputer terminology
Computer terminologykeki3
 
Introduction to programming
Introduction to programmingIntroduction to programming
Introduction to programmingkeki3
 
2019年度 若手技術者向け講座 デザインパターン 演習問題
2019年度 若手技術者向け講座 デザインパターン 演習問題2019年度 若手技術者向け講座 デザインパターン 演習問題
2019年度 若手技術者向け講座 デザインパターン 演習問題keki3
 
2019年度 若手技術者向け講座 デザインパターン
2019年度 若手技術者向け講座 デザインパターン2019年度 若手技術者向け講座 デザインパターン
2019年度 若手技術者向け講座 デザインパターンkeki3
 
2019年度 若手技術者向け講座 リファクタリング
2019年度 若手技術者向け講座 リファクタリング2019年度 若手技術者向け講座 リファクタリング
2019年度 若手技術者向け講座 リファクタリングkeki3
 
2019年度 若手技術者向け講座 UML
2019年度 若手技術者向け講座 UML2019年度 若手技術者向け講座 UML
2019年度 若手技術者向け講座 UMLkeki3
 
2019年度 若手技術者向け講座 オブジェクト指向
2019年度 若手技術者向け講座 オブジェクト指向2019年度 若手技術者向け講座 オブジェクト指向
2019年度 若手技術者向け講座 オブジェクト指向keki3
 
Wakatemukekouza2019 web
Wakatemukekouza2019 webWakatemukekouza2019 web
Wakatemukekouza2019 webkeki3
 
2019 若手技術者向け講座 DB設計
2019 若手技術者向け講座 DB設計2019 若手技術者向け講座 DB設計
2019 若手技術者向け講座 DB設計keki3
 
2019年度 若手技術者向け講座 NoSQL
2019年度 若手技術者向け講座 NoSQL2019年度 若手技術者向け講座 NoSQL
2019年度 若手技術者向け講座 NoSQLkeki3
 
2019年度 若手技術者向け講座 DBMSの機能
2019年度 若手技術者向け講座 DBMSの機能2019年度 若手技術者向け講座 DBMSの機能
2019年度 若手技術者向け講座 DBMSの機能keki3
 
2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画keki3
 
2019年度若手技術者向け講座 インデックス
2019年度若手技術者向け講座 インデックス2019年度若手技術者向け講座 インデックス
2019年度若手技術者向け講座 インデックスkeki3
 
2019年度 若手技術者向け講座 SQL演習
2019年度 若手技術者向け講座 SQL演習2019年度 若手技術者向け講座 SQL演習
2019年度 若手技術者向け講座 SQL演習keki3
 
2018年度 若手技術者向け講座 デザインパターン
2018年度 若手技術者向け講座 デザインパターン2018年度 若手技術者向け講座 デザインパターン
2018年度 若手技術者向け講座 デザインパターンkeki3
 
2018年度 若手技術者向け講座 UML
2018年度 若手技術者向け講座 UML2018年度 若手技術者向け講座 UML
2018年度 若手技術者向け講座 UMLkeki3
 
2018年度 若手技術者向け講座 オブジェクト指向01
2018年度 若手技術者向け講座 オブジェクト指向012018年度 若手技術者向け講座 オブジェクト指向01
2018年度 若手技術者向け講座 オブジェクト指向01keki3
 
2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリングkeki3
 
2018年度 若手技術者向け講座 DB設計・正規化
2018年度 若手技術者向け講座 DB設計・正規化2018年度 若手技術者向け講座 DB設計・正規化
2018年度 若手技術者向け講座 DB設計・正規化keki3
 
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理keki3
 

More from keki3 (20)

Computer terminology
Computer terminologyComputer terminology
Computer terminology
 
Introduction to programming
Introduction to programmingIntroduction to programming
Introduction to programming
 
2019年度 若手技術者向け講座 デザインパターン 演習問題
2019年度 若手技術者向け講座 デザインパターン 演習問題2019年度 若手技術者向け講座 デザインパターン 演習問題
2019年度 若手技術者向け講座 デザインパターン 演習問題
 
2019年度 若手技術者向け講座 デザインパターン
2019年度 若手技術者向け講座 デザインパターン2019年度 若手技術者向け講座 デザインパターン
2019年度 若手技術者向け講座 デザインパターン
 
2019年度 若手技術者向け講座 リファクタリング
2019年度 若手技術者向け講座 リファクタリング2019年度 若手技術者向け講座 リファクタリング
2019年度 若手技術者向け講座 リファクタリング
 
2019年度 若手技術者向け講座 UML
2019年度 若手技術者向け講座 UML2019年度 若手技術者向け講座 UML
2019年度 若手技術者向け講座 UML
 
2019年度 若手技術者向け講座 オブジェクト指向
2019年度 若手技術者向け講座 オブジェクト指向2019年度 若手技術者向け講座 オブジェクト指向
2019年度 若手技術者向け講座 オブジェクト指向
 
Wakatemukekouza2019 web
Wakatemukekouza2019 webWakatemukekouza2019 web
Wakatemukekouza2019 web
 
2019 若手技術者向け講座 DB設計
2019 若手技術者向け講座 DB設計2019 若手技術者向け講座 DB設計
2019 若手技術者向け講座 DB設計
 
2019年度 若手技術者向け講座 NoSQL
2019年度 若手技術者向け講座 NoSQL2019年度 若手技術者向け講座 NoSQL
2019年度 若手技術者向け講座 NoSQL
 
2019年度 若手技術者向け講座 DBMSの機能
2019年度 若手技術者向け講座 DBMSの機能2019年度 若手技術者向け講座 DBMSの機能
2019年度 若手技術者向け講座 DBMSの機能
 
2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画2019年度 若手技術者向け講座 実行計画
2019年度 若手技術者向け講座 実行計画
 
2019年度若手技術者向け講座 インデックス
2019年度若手技術者向け講座 インデックス2019年度若手技術者向け講座 インデックス
2019年度若手技術者向け講座 インデックス
 
2019年度 若手技術者向け講座 SQL演習
2019年度 若手技術者向け講座 SQL演習2019年度 若手技術者向け講座 SQL演習
2019年度 若手技術者向け講座 SQL演習
 
2018年度 若手技術者向け講座 デザインパターン
2018年度 若手技術者向け講座 デザインパターン2018年度 若手技術者向け講座 デザインパターン
2018年度 若手技術者向け講座 デザインパターン
 
2018年度 若手技術者向け講座 UML
2018年度 若手技術者向け講座 UML2018年度 若手技術者向け講座 UML
2018年度 若手技術者向け講座 UML
 
2018年度 若手技術者向け講座 オブジェクト指向01
2018年度 若手技術者向け講座 オブジェクト指向012018年度 若手技術者向け講座 オブジェクト指向01
2018年度 若手技術者向け講座 オブジェクト指向01
 
2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング2018年度 若手技術者向け講座 リファクタリング
2018年度 若手技術者向け講座 リファクタリング
 
2018年度 若手技術者向け講座 DB設計・正規化
2018年度 若手技術者向け講座 DB設計・正規化2018年度 若手技術者向け講座 DB設計・正規化
2018年度 若手技術者向け講座 DB設計・正規化
 
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理
2018年度 若手技術者向け講座 大量データの扱い・ストアド・メモリ管理
 

2018年度 若手技術者向け講座 SQL概要