気軽にコメントしようとしたら長くなったのでこっち
こちらに外野から反応してみる。
http://d.hatena.ne.jp/aufheben/20070624/1182708030
「第3章 その2」なんですが、以前出向してた会社に、GROUP BYの中を書くのが面倒くさいので、集計する列以外全部MAXかMINをつけてる人がいました。そっちのが面倒な気もするんですが、まあそういう価値観は人それぞれ。
で、面倒とかでなくスカラー要素で考えるとなると、無駄に関数を呼んでそれだけオーバーヘッドになるのと、GROUP BYを書く事でソートが走るのと比べた時、後者の方が効率がよいと思いますので、なるたけGROUP BYに入れる解答1がよいかと思います。
サブクエリにして事前に絞り込んでおくのも同様、単純にSELECT回数が増える訳でそれもオーバーヘッドになるでしょうから、どうしたもんかと都度考える。
確かに集計単位たる都道府県IDのただの属性をGROUP BYに入れるのに、なにか気持ち悪い気がするのは判ります。ちゃんと頭にER図が入ってないとダメですからねぇ。この場合は単純なのでまだいいですが、もっと複雑な集計SQLを書く時なんかは特にそうです。まず基本の集計単位(ここでは都道府県ID)でSQL書いて、後から名称などをGROUP BYに追加したら、その前と集計値及びレコード件数が変わらないか確かめつつやってますね、そう云えば。
「第3章 その6」は、サブクエリをJOINすると、その商品の売上が無かった場合に取ってこれない。この場合は平均を上回った場合なのでいいのですが、他色々と条件を変えて応用を利かせようとすると、解答1形式の方が使いでがある。
じゃあJOINをLEFT JOINにすりゃいいじゃんって話になるんですが、売上ってかなりの件数なのでそりゃもう重たくなるんですよねぇ。
例えば、全商品の一覧を出して、売り上げた商品の点数を集計する場合、売上がなかったら0と出す。
SELECT p.product_id, p.product_name, SUM(COALESCE(s.quantity,0)) FROM Product p LEFT JOIN Sales s ON p.product_id = s.product_id GROUP BY p.product_id, p.product_name
より、
SELECT p.product_id, p.product_name, COALESCE( ( SELECT SUM(s.quantity) FROM Sales s WHERE s.product_id = p.product_id ) ,0) FROM Product p
のが早いと思います。以前似たような件があって、下のに変えたら実際驚く程に早くなりました。
メモ帳でつらつら書いてるので、上の奴、正しく動くかどうかわかんないんですけども。