もう一つ,
カルテ2:先ほどの2つのテーブルOrders
- {注文番号,
注文者名義, 受付日, 商品数}
再び,SQLで解くなら
商品の数はOrderReceiptsテーブルのほうを注文番号別にカウントする必要がある。一方で注文者名義や受付日はOrdersテーブルを参照しなければならない。これもやはり素直に解くのなら,
集約について注意が必要なのは,
……わかった! さっきと同じで,
リスト4 ワイリーの解:集約関数を使う
SELECT O.order_id,
MAX(O.order_name) AS order_name,
MAX(O.order_date) AS order_date,
COUNT(*) AS item_count
FROM Orders O
INNER JOIN OrderReceipts ORC
ON O.order_id = ORC.order_id
GROUP BY O.order_id;
図6 リスト4の実行結果
order_id | order_name | order_date | item_count ---------+------------+------------+------------ 10000 | 後藤信二 | 2011-08-22 | 3 10001 | 佐原商店 | 2011-09-01 | 1 10002 | 水原陽子 | 2011-09-20 | 2 10003 | 加地健太郎 | 2011-08-05 | 3 10004 | 相原酒店 | 2011-08-22 | 1 10005 | 宮元雄介 | 2011-08-29 | 2
それでいいわ。もう一つのやり方としては,
リスト5 ヘレンの解:ウィンドウ関数を使う
SELECT O.order_id,
O.order_name,
O.order_date,
COUNT(*) OVER (PARTITION BY O.order_id) AS item_count
FROM Orders O
INNER JOIN OrderReceipts ORC
ON O.order_id = ORC.order_id;
※ MySQLはウィンドウ関数をサポートしていない
図7 リスト5の実行結果
order_id | order_name | order_date | item_count ---------+------------+------------+------------ 10000 | 後藤信二 | 2011-08-22 | 3 10000 | 後藤信二 | 2011-08-22 | 3 10000 | 後藤信二 | 2011-08-22 | 3 10001 | 佐原商店 | 2011-09-01 | 1 10002 | 水原陽子 | 2011-09-20 | 2 10002 | 水原陽子 | 2011-09-20 | 2 10003 | 加地健太郎 | 2011-08-05 | 3 10003 | 加地健太郎 | 2011-08-05 | 3 10003 | 加地健太郎 | 2011-08-05 | 3 10004 | 相原酒店 | 2011-08-22 | 1 10005 | 宮元雄介 | 2011-08-29 | 2 10005 | 宮元雄介 | 2011-08-29 | 2
あれ,
構文上は別になくてもいいし,
ふう,
ワイリーの解
図8 実行計画:集約関数
QUERY PLAN -------------------------------------------------------------------------------- HashAggregate (cost=50.94..57.94 rows=400 width=90) ― 図9と異なる部分(GROUP BY) -> Hash Join (cost=19.00..44.44 rows=650 width=90) Hash Cond: (orc.order_id = o.order_id) -> Seq Scan on orderreceipts orc (cost=0.00..16.50 rows=650 width=4) -> Hash (cost=14.00..14.00 rows=400 width=90) -> Seq Scan on orders o (cost=0.00..14.00 rows=400 width=90)
図9 実行計画:ウィンドウ関数
-------------------------------------------------------------------------------------- WindowAgg (cost=74.81..86.18 rows=650 width=90) -> Sort (cost=74.81..76.43 rows=650 width=90) Sort Key: o.order_id ― 図8と異なる部分(ウィンドウ関数の集約操作) -> Hash Join (cost=19.00..44.44 rows=650 width=90) Hash Cond: (orc.order_id = o.order_id) -> Seq Scan on orderreceipts orc (cost=0.00..16.50 rows=650 width=4) -> Hash (cost=14.00..14.00 rows=400 width=90) -> Seq Scan on orders o (cost=0.00..14.00 rows=400 width=90)
そのため,
- 注4)
- 宿題の解答は,
技術評論社のWEB+DB PRESS本誌サポートサイトおよび筆者のサポートサイトで公開します。
モデル変更で解く方法
SQLによる解はこのぐらいで良いだろう。ではさっきと同じように,
やはりOrdersテーブルに
うむ。Ordersテーブルが最初からこういう定義であったなら,
それはちょっとフールプルーフの思想を曲解しているような……まあいいけど。あと,
たしかに。そうなると結局,