気軽にコメントしようとしたら長くなったのでこっち

こちらに外野から反応してみる。
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

のが早いと思います。以前似たような件があって、下のに変えたら実際驚く程に早くなりました。

メモ帳でつらつら書いてるので、上の奴、正しく動くかどうかわかんないんですけども。