13. 基本構文
• SELECTの基本構文
13
-- レコードの並び替え
SELECT *
FROM テーブル名
ORDER BY カラム名1, ... (ASC|DESC) ;
-- 集約
SELECT ...
FROM テーブル名
GROUP BY カラム名1, ...
HAVING 絞り込み条件;
-- レコード件数の制限
SELECT *
FROM テーブル名
LIMIT 件数;
14. 基本構文
• SELECTの基本構文
• よく使用されるSQLの構文の組み合わせです。
14
-- 基本構文
SELECT カラム1, ... -- 取得したいカラムリスト
FROM テーブル名 -- レコードの取得対象のテーブル
JOIN句 結合対象テーブル -- 結合対象のテーブル
ON 結合条件 -- 結合条件
WHERE 絞込条件1 ... -- レコードの絞り込み
GROUP BY カラム1, ... -- 集約
HAVING 絞り込み条件 -- 集約後の絞り込み
ORDER BY カラム1, ... -- 並び替え
;
17. 基本構文
• SQLで使用できる演算子
• 比較演算子
• = : 等しい
• <> : 等しくない(!=でも可)
• >=、<=、>、< : 以上、以下、大なり、小なり
• IS : NULL判定で使用
• 論理演算子
• NOT:否定
• AND:論理積
• OR : 論理和
17
-- 比較演算子と論理演算子
SELECT ...
FROM table1
WHERE column1 >= 10 AND column2 = 'a'
AND column3 IS NOT NULL;
18. 基本構文
• WHERE句でよく使用する演算子
• IN:ORによる複数の条件指定を一つにまとめます。
• LIKE:あいまい検索での絞り込みをします。
• BETWEEN:カラムに対して範囲指定で絞り込みをします。
18
-- WHERE句で使用する演算子
SELECT ...
FROM table1
WHERE colmn1 IN ('AAA', 'BBB', 'CCC')
AND column2 LIKE '%ABC%'
AND column3 BETWEEN 100 AND 200
;
22. GROUP BY
• GROUP BY
• GROUP BY は複数のレコードを1行にまとめる場合に使用します。
• 集約関数(COUNT, SUM, MAX, MIN, AVGなど)と組み合わせて使用する場合が
多いです。
• 集約関数の結果に対して絞り込み条件を指定する場合は、HAVING句を使用し
ます。
22
-- 例
SELECT column1, SUM(column2), COUNT(*)
FROM table1
GROUP BY column1
HAVING SUM(column2) > 10000;
23. GROUP BY
• GROUP BY
• 集約関数を適用しないカラムで絞り込みを行う場合、WHERE句で絞り込む方
法とHAVING句で絞り込む方法があります。
• 結果は同じになりますが、パフォーマンスに差が出る場合があります。
23
-- 例①
SELECT column1, SUM(column2)
FROM table1
WHERE column1 = 200
GROUP BY column1 ;
-- 例②
SELECT column1, SUM(column2)
FROM table1
GROUP BY column1
HAVING column1 = 200;
34. ORDER BY
• ORDER BY
• SELECT文を実行した際の結果の並び順を指定したい場合にはORDER BY
句を指定します。
• 並び替えの基準となるカラムを指定し、昇順の場合はASC, 降順の場合
はDESCを指定します。省略した場合は昇順となります。
• カラムは複数指定することも可能です。その場合、優先順位の高いも
のから順に記述していきます。
34
-- 書き方
SELECT句
FROM句
WHERE句
ORDER BY column1 (ASC|DESC), column2 (ASC|DESC),…
48. 内部結合
• 内部結合(解答)
48
内部結合
ex_items
id item_name
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
ex_item_price
id price
1 100
2 160
3 80
7 300
8 200
9 600
id item_name price
1 りんご 100
2 バナナ 160
3 オレンジ 80
SELECT item.id, item_name, price
FROM ex_items item
INNER JOIN ex_item_price ex_price
ON item.id = ex_price.id
ORDER BY item.id;
idをキーとした内部結合
idが一致するレコードのみが
抽出されます。
49. 外部結合
• 外部結合
• 外部結合は3つの種類があります。
• 左外部結合、右外部結合、全外部結合、の3つです。
• 左外部結合と右外部結合は、実質的に同じです。
• 全外部結合はDBMSによってはサポートされていないので注意が必要で
す。
49
-- 書き方(左外部結合)
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
50. 外部結合
• 左外部結合(例)
50
SELECT i.id, item_name, price
FROM ex_items i
LEFT OUTER JOIN ex_item_price p
ON i.id = p.id
ORDER BY i.id;
左外部結合
ex_items
id item_name
1 りんご
2 バナナ
3 オレンジ
4 ぶどう
5 いちご
6 メロン
ex_item_price
id price
1 100
2 160
3 80
7 300
8 200
9 600
id item_name price
1 りんご 100
2 バナナ 160
3 オレンジ 80
4 ぶどう (NULL)
5 いちご (NULL)
6 メロン (NULL)
51. 外部結合
• 左外部結合(注意点)
• 違いが分かりますか?
51
-- 結合条件での絞り込み
SELECT i.id, item_name, price
FROM ex_items i
LEFT OUTER JOIN ex_item_price p
ON i.id = p.id
AND p.price >= 100
ORDER BY i.id;
-- 結合後の条件での絞り込み
SELECT i.id, item_name, price
FROM ex_items i
LEFT OUTER JOIN ex_item_price p
ON i.id = p.id
WHERE p.price >= 100
ORDER BY i.id;
52. 外部結合
• 左外部結合(注意点)
• 結果はこうなります。
52
-- 結合条件での絞り込み
SELECT i.id, item_name, price
FROM ex_items i
LEFT OUTER JOIN ex_item_price p
ON i.id = p.id
AND p.price >= 100
ORDER BY i.id;
-- 結合後の条件での絞り込み
SELECT i.id, item_name, price
FROM ex_items i
LEFT OUTER JOIN ex_item_price p
ON i.id = p.id
WHERE p.price >= 100
ORDER BY i.id;
id item_name price
1 りんご 100
2 バナナ 160
3 オレンジ (NULL)
4 ぶどう (NULL)
5 いちご (NULL)
6 メロン (NULL)
id item_name price
1 りんご 100
2 バナナ 160
64. UNION
• UNIONとUNION ALL
• 3つのSELECT文の和集合の結果を得るための演算子。
• それぞれの演算子で何が違うが分かりますか?
64
-- 書き方
SELECT文①
UNION
SELECT文②
-- 書き方
SELECT文①
UNION ALL
SELECT文②
65. UNION
• UNIONとUNION ALL
• 3つのSELECT文の和集合の結果を得るための演算子。
• UNION と UNION ALL の違いは、SELECT文①とSELECT文②に重複があっ
た場合に現れます。
• UNION単独の場合、重複は削除して1行のみ表示します。UNION ALL は、
重複もそのまま表示します。
• パフォーマンス面ではUNION ALLの方が高速になります。UNIONは、重
複排除のために内部でソートの処理を行いますが、UNION ALLではソー
トの処理は行われません。そのため速度に違いがでます。
65
-- 書き方
SELECT文①
UNION
SELECT文②
-- 書き方
SELECT文①
UNION ALL
SELECT文②
78. サブクエリ
• サブクエリ
• 副問い合わせとも呼ばれます。
• SELECT文の結果を別のクエリ(SQL文)に使用する書き方。
• FROM句として使用したり、結合対象としてサブクエリを使用するこ
とも多いです。
• 更新系のSQLでも使用することができます。
78
-- 例(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
79. サブクエリ
• サブクエリ(例)
79
-- 例(販売数を商品で集約した結果を、結合に使用する)
SELECT i.*, sum
FROM ex_item_sub i
LEFT OUTER JOIN (SELECT item_id, SUM(quantity) sum
FROM ex_sales_sub
GROUP BY item_id) s
ON i.item_id = s.item_id
ORDER BY i.item_id;
ex_item_sub
item_id item_name price
001 商品A 200
002 商品B 350
003 商品C 170
004 商品D 200
005 商品E 300
ex_sales_sub
sales_date item_id quantity
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
item_id item_name price sum
001 商品A 200 35
002 商品B 350 70
003 商品C 170 50
004 商品D 200 (NULL)
005 商品E 300 (NULL)
80. サブクエリ
• 相関サブクエリ
• 外側のクエリの値を内側のクエリ内で使用するサブクエリ
• よく使用されるのはEXISTSを使用したSQL文
80
-- 例(table2に、idが一致するレコードが存在するtable1のレコードを表示)
SELECT * FROM table1 t1
WHERE EXISTS (SELECT * FROM table2 t2
WHERE t1.id = t2.id)
-- INを使用したEXISTSの代用
SELECT * FROM table1 t1
WHERE id IN (SELECT id FROM table2 t2)
81. サブクエリ
• 相関サブクエリ(例)
81
-- 9/1~9/3の期間に一度でも販売された商品を取得するSQL文
SELECT * FROM ex_item_sub i
WHERE EXISTS (SELECT * FROM ex_sales_sub
WHERE item_id = i.item_id
AND sales_date BETWEEN '2018/9/1' AND '2018/9/3');
ex_item_sub
item_id item_name price
001 商品A 200
002 商品B 350
003 商品C 170
004 商品D 200
005 商品E 300
ex_sales_sub
sales_date item_id quantity
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
item_id item_name price
001 商品A 200
002 商品B 350
82. サブクエリ
• スカラ・サブクエリ
• SELECT句の中にサブクエリを記述する方法。
• 結果がイメージしやすいが、多用するとパフォーマンスが悪くなる。
82
-- SELECT句の中で、別のテーブルのレコードを取得する
SELECT id
, (SELECT name
FROM table2
WHERE id = table1.id) エイリアス名
FROM table1
85. CASE式
• CASE式
• SQLで条件分岐をするための構文です。
• SELECT句、WHERE句、GROUP BY句のなど、どこでも使用可能です。
• 一般的にはWHERE句では使用せずにSELECT句の中で使用することが多
い。
• maxや、sumなどの集約関数の中に入れ込むこともある。
85
-- 書き方
SELECT
CASE
WHEN 条件式1 THEN 値1
WHEN 条件式2 THEN 値2
ELSE 値3
END エイリアス名
FROM table2
87. CASE式
• CASE式(解答)
87
-- 単価によってランクを決める
SELECT *
, CASE
WHEN price >= 10000 THEN '高級品'
WHEN price BETWEEN 5000 AND 9999 THEN '普通'
ELSE '安物'
END rank
FROM ex_item_case;
ex_item_case
item_id item_name price
001 商品A 1000
002 商品B 5000
003 商品C 10000
item_id item_name price rank
001 商品A 1000 安物
002 商品B 5000 普通
003 商品C 10000 高級品
88. CASE式
• CASE式(SELECT句以外での使用)
• CASE式はGROUP BY句でORDER BY句でも使用可能です。
88
-- 単価のランクでグループ化するし、ランクごとに集計する
SELECT sum(price)
, CASE
WHEN price >= 10000 THEN 'A'
WHEN price BETWEEN 5000 AND 9999 THEN 'B'
ELSE 'C'
END rank
FROM ex_item_case
GROUP BY CASE
WHEN price >= 10000 THEN 'A'
WHEN price BETWEEN 5000 AND 9999 THEN 'B'
ELSE 'C'
END rank;
107. SQLの速度
• INとEXISTS
• サブクエリで条件指定してレコードを取得する場合、INによる書き方
とEXISTSによる書き方があります。
• 下の2つの書き方は同じ結果になります。どちらがパフォーマンス的
にすぐれているでしょうか。
107
-- 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);
109. SQLの速度
• 結合+DISTINCTとEXISTS
• INやEXISTSと同じ結果を得るために、結合を用いることもできます。
• ただし結合を使用する場合は、結果を一意にするためにDISTINCTが必
要な場面もあります。
109
-- 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
111. SQLの速度
• UNIONとUNION ALL
• UNIONとUNION ALL では、UNION ALLの方が高速です。
• 理由は、UNIONは重複削除のためにソートの処理を行うためです。
• そのため、重複がないことが分かっている場合や、ソートの必要がな
い場合はUNION ALLを使用することにしましょう。
111
112. SQLの速度
• HAVINGとWHERE
• GROUP BY句を使用する場合、HAVING句とWHERE句による絞り込みが可
能です。例えば以下の2つのSQL文は同じ結果になります。
112
-- 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