4. 集約&整列&リネーム演算 - 例
• 安価なワインの産地別平均価格(降順)
• 安価=ワインの価格が4000円未満=安価なワイン
• 安価=産地平均価格が4000円未満=安価な産地
データベースシステム論 第 回2015 [ 7 ] 4p.
SELECT did, round(avg(price)) FROM wine
WHERE price < 4000 GROUP BY did
ORDER BY round DESC;
SELECT did, round(avg(price)) FROM wine
GROUP BY did HAVING avg(price) < 4000
ORDER BY round DESC;
did | round
-----+-------
C | 2800
A | 2700
B | 2200
did | round
-----+-------
C | 2800
A | 2700
5. 考え方の一例
• 4000円”以下”で考えてみよう
• 安価=ワインの価格が4000円以下=安価なワイン
• 安価=産地平均価格が4000円以下=安価な産地
データベースシステム論 第 回2015 [ 7 ] 5p.
SELECT did, round(avg(price)) FROM wine
WHERE price <= 4000 GROUP BY did
ORDER BY round DESC;
SELECT did, round(avg(price)) FROM wine
GROUP BY did HAVING avg(price) <= 4000
ORDER BY round DESC;
did | round
-----+-------
D | 4000
C | 2800
A | 2700
B | 2200
did | round
-----+-------
B | 4000
D | 4000
C | 2800
A | 2700
wID name dID price
3 サンテミリオン B 5800
4 オーメドック B 2200
12. 自然結合 - 例
• 外部キー同士のカラム名が同じなら自然結合を
使えば楽に(結合条件無しに)SQLを書けます
データベースシステム論 第 回2015 [ 8 ] 12p.
SELECT * FROM wine NATURAL JOIN vineyard;
did | wid | name | price | district
-----+-----+------------------------+-------+----------------
A | 1 | シャブリ | 2400 | ブルゴーニュ
A | 2 | ジュヴレシャンベルタン | 3000 | ブルゴーニュ
B | 3 | サンテミリオン | 5800 | ボルドー
B | 4 | オーメドック | 2200 | ボルドー
C | 5 | サンセール | 2800 | ロワール
D | 6 | シャンパン | 4000 | シャンパーニュ
(6 行)
13. 外部結合 - 試行課題2(提出無)
• 結果が違うのはどれ?そしてなぜ?
データベースシステム論 第 回2015 [ 8 ] 13p.
SELECT wid, name, district, price
FROM wine [LEFT|FULL|RIGHT] JOIN vineyard
ON wine.did = vineyard.did;
wID name dID price
1 シャブリ A 2400
2 ジュヴレシャンベルタン A 3000
3 サンテミリオン B 5800
4 オーメドック B 2200
5 サンセール C 2800
6 シャンパン D 4000
dID district
A ブルゴーニュ
B ボルドー
C ロワール
D シャンパーニュ
E チリ
wine vineyard
14. 外部結合 - 試行課題2
• wine LEFT JOIN vineyard
• ●にある行を全て得る
• wine FULL JOIN vineyard
• ●と●にある行を全て得る
• wine RIGHT JOIN vineyard
• ●にある行を全て得る
データベースシステム論 第 回2015 [ 8 ] 14p.
wID name dID price
1 シャブリ A 2400
2 ジュヴレシャンベルタン A 3000
3 サンテミリオン B 5800
4 オーメドック B 2200
5 サンセール C 2800
6 シャンパン D 4000
dID district
A ブルゴーニュ
B ボルドー
C ロワール
D シャンパーニュ
E チリ
wine vineyard
A
B
C
D
E
右左
• 対応する行がwineに無い
• NULLで埋まる
15. 外部結合 - 試行課題2
• wine LEFT JOIN vineyard
• ●にある行を全て得る
• wine FULL JOIN vineyard
• ●と●にある行を全て得る
• wine RIGHT JOIN vineyard
• ●にある行を全て得る
データベースシステム論 第 回2015 [ 8 ] 15p.
wID name dID price
1 シャブリ A 2400
2 ジュヴレシャンベルタン A 3000
3 サンテミリオン B 5800
4 オーメドック B 2200
5 サンセール C 2800
6 シャンパン D 4000
dID district
A ブルゴーニュ
B ボルドー
C ロワール
D シャンパーニュ
E チリ
wine vineyard
A
B
C
D
E
右左
• 対応する行がwineに無い
• NULLで埋まる
wid | name | district | price
-----+------------------------+----------------+-------
1 | シャブリ | ブルゴーニュ | 2400
2 | ジュヴレシャンベルタン | ブルゴーニュ | 3000
3 | サンテミリオン | ボルドー | 5800
4 | オーメドック | ボルドー | 2200
5 | サンセール | ロワール | 2800
6 | シャンパン | シャンパーニュ | 4000
| | チリ |
(7 行)
22. スカラー副問い合わせ - 例
• 価格の一番安いワイン
データベースシステム論 第 回2015 [ 8 ] 22p.
SELECT * FROM wine
WHERE price= (
SELECT min(price) FROM wine);
dbsys=# SELECT * FROM wine
dbsys-# WHERE wid = (
dbsys(# SELECT min(wid) FROM wine);
wid | name | did | price
-----+--------------+-----+-------
4 | オーメドック | B | 2200(1 行)
23. 試行課題3 考えてみよう!
• 一番安いワインは次の問い合わせでもOKでは?
データベースシステム論 第 回2015 [ 8 ] 23p.
SELECT * FROM wine ORDER BY price LIMIT 1;
最初のn件を出す
SELECT * FROM wine
WHERE price= (
SELECT min(price) FROM wine);
例のテーブルでは同じ結果を得ますが。これはたまたまです。
さて、この二つの問い合わせは何が異なっているでしょうか。
考えてみましょう。
24. 試行課題3 考えてみよう!
• 一番安いワインは次の問い合わせでもOKでは?
データベースシステム論 第 回2015 [ 8 ] 24p.
SELECT * FROM wine ORDER BY price LIMIT 1;
最初のn件を出す
SELECT * FROM wine
WHERE price= (
SELECT min(price) FROM wine);
答えのヒント!
もし最安値で二種類以上のワインがあったら?
25. 相関副問い合わせ - 例
• 産地毎の一番安いワイン
データベースシステム論 第 回2015 [ 8 ] 25p.
SELECT * FROM wine AS x
WHERE price = (
SELECT min(price)
FROM wine AS y
GROUP BY did
HAVING x.did = y.did);
主問い合わせを参照する副問い合わせ
min
------
4000
2200
2800
2400
D
B
C
A
did
オーメドック
シャンパン
サンセール
シャブリ
wid | name | did | price
-----+--------------+-----+-------
1 | シャブリ | A | 2400
4 | オーメドック | B | 2200
5 | サンセール | C | 2800
6 | シャンパン | D | 4000
26. IN句、NOT IN句
• 右辺は括弧で括られた副問い合わせ
• 一列のみを返す式でないとならない
• 左辺が右辺副問い合わせの結果行のどれかと等
しい場合「真」となる。(NOT INはその逆)
データベースシステム論 第 回2015 [ 8 ] 26p.
mainquery
WHERE 左辺 [NOT] IN subquery
SELECT * FROM vineyard
WHERE did NOT IN
(SELECT DISTINCT did FROM wine);
IN句と似たような使い方の句とし
てSOME(ANY)句、ALL句があります。
これらは教科書を見てください。
28. アンチ結合の例に戻りましょう
• EXISTS句:主問い合わせが先に実行される
データベースシステム論 第 回2015 [ 8 ] 28p.
SELECT *
FROM vineyard
WHERE NOT EXISTS (
SELECT NULL
FROM wine
WHERE vineyard.did = wine.did);
• vineyardを副問い合わせで参照している
• →相関副問い合わせ
dID district
A ブルゴーニュ
B ボルドー
C ロワール
D シャンパーニュ
E チリ
vineyard
「wineテーブルにありますか?」「EXISTS!」
「wineテーブルにありますか?」「EXISTS!」
「wineテーブルにありますか?」「EXISTS!」
「wineテーブルにありますか?」「EXISTS!」
「wineテーブルにありますか?」「NOT EXISTS!」
did | district
-----+----------
E | チリ
(1 行)
29. アンチ結合をNOT IN句で書く
• IN句:副問い合わせが先に実行される
データベースシステム論 第 回2015 [ 8 ] 29p.
SELECT *
FROM vineyard
WHERE did NOT IN(
SELECT DISTINCT did
FROM wine);
did | district
-----+----------
E | チリ
(1 行)
wID name dID price
1 シャブリ A 2400
2 ジュヴレシャンベルタン A 3000
3 サンテミリオン B 5800
4 オーメドック B 2200
5 サンセール C 2800
6 シャンパン D 4000
wine
dID
A
B
C
D
subquery
dID district
A ブルゴーニュ
B ボルドー
C ロワール
D シャンパーニュ
E チリ
vineyard
無いっ!
30. 和演算
• UNION句、UNION ALL句
• スキーマが同一のテーブルを縦方向につなげる
• やってみよう!違いは何?
データベースシステム論 第 回2015 [ 8 ] 30p.
SELECT * FROMテーブル名1
UNION [ALL] SELECT * FROMテーブル名2
SELECT * FROM wine
UNION SELECT * FROM wine;
SELECT * FROM wine
UNION ALL SELECT * FROM wine;
31. 結果の一部表示
• LIMIT句、OFFSET句
• 結果中m番目からn行表示する
• ORDER BY句と一緒に使用する
データベースシステム論 第 回2015 [ 8 ] 31p.
SELECT * FROMテーブル名
ORDER BYソートの基準列 [並び方],…
LIMIT n OFFSET m;
SELECT * FROM wine
ORDER BY price desc
LIMIT 2 OFFSET 3;