みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

GROUP BYの記述方法について

GROUP BYの記述方法について教えてください

---------------------
受注データ(テーブル)
---------------------
品目CD 受注数
00001  10
00001  10
00002  20
00002  15

---------------------
品目マスタ(テーブル)
---------------------
品目CD 品目名
00001  えんぴつ
00002  けしごむ
00003  色鉛筆

上記二つのDBから、品目ごとの受注数の合計を取得するときのSQL文として、どうするのが正しいのでしょうか?
---------------------
欲しい結果
---------------------
品目CD 品目名  受注数
00001 えんぴつ 20
00002 けしごむ 35

(考えられるSQL)
CASE1:受注データの品目CDと品目マスタの品目名のグループ化
SELECT A.品目CD, B.品目名, SUM(A.受注数)
FROM 受注データ A, 品目マスタ B
WHERE A.品目CD = B.品目CD
GROUP BY A.品目CD, B.品目名

CASE2:受注データをグループ化した結果と品目マスタを結合
SELECT X.品目CD, X.受注数合計, Y.品目名
FROM
 (SELECT 品目CD, SUM(受注数)
  FROM 受注データ
  GROUP BY 品目CD)X,品目マスタ Y
WHERE X.品目CD = Y.品目CD

CASE3:品目マスタの品目CDと品目名のグループ化
SELECT B.品目CD, B.品目名, SUM(A.受注数)
FROM 受注データ A, 品目マスタ B
WHERE A.品目CD = B.品目CD
GROUP BY B.品目CD, B.品目名

レスポンスも含めて教えてください。
よろしく、お願いします。

投稿日時 - 2008-09-05 23:33:08

QNo.4306815

困ってます

質問者が選んだベストアンサー

#1です。蛇足以外のなにものでもないんですけど、追加質問に対してコメントしておきます。
実行上のレスポンスは全く変わらないです。

CASE1のクエリを書く人は実際は多いと思います。それはこのクエリのメインの目的は受注数を出すことであって、商品名を出すことではないからです。
例のクエリがシンプルですから、頭の中で全部組み上げて一気にかけますが、もっと複雑なクエリになってくると、本当に必要な数字が取れることを確認してから付随情報を付加していくように書くと思います。

つまり、まず
SELECT A.品目CD, SUM(A.受注数)
FROM 受注データ A
GROUP BY A.品目CD
というクエリを書いて想定される数字が出せるかどうか確認し、
それから
SELECT A.品目CD, B.品目名, SUM(A.受注数)
FROM 受注データ A
INNER JOIN 品目マスタ B ON B.品目CD=A.品目CD
GROUP BY A.品目CD,B.品目名
と書き足します。

したがって、CASE1のメリットをあげるとすれば、「書きやすい」ことでしょうか。

ここまで来ると個人的な意見にすぎませんけどね。

投稿日時 - 2008-09-08 02:03:08

お礼

わかりやすい解説、ありがとうございます。
大変参考になりました。

投稿日時 - 2008-09-08 22:56:51

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

既に#1さんが丁寧な回答をされていますが
自分で複数のアプローチのSQLを考えることができて
レスポンスについても気にしている段階にいるのであれば
実行計画の読み方について勉強すれば良いと思います。
オラクル固有の表現もありますが、他のDBMSを使用するにあたっても
基本的な表示やロジックは同じですので得た知識を流用できます。

#既に実行計画が読めるのであれば実行計画も添付すると回答がしやすくなります。

投稿日時 - 2008-09-06 16:32:53

補足

回答ありがとうございます。
参考にさせていただきます。

投稿日時 - 2008-09-07 11:36:13

お礼

回答ありがとうございます。
参考にさせていただきます。

投稿日時 - 2008-09-07 11:37:20

ANo.1

まあ、一つの意見として見てください。
1つ目の見方は、「どのやり方も正しい」です。
後述しますが、どの書き方をしてもレスポンスに大きな差は生じません。また、どの書き方をしても実務上「その書き方は間違っている」と怒られることもないはずです。

2つ目の見方は、「CASE3の書き方が最もメンテナンスしやすい」です。
今回は条件が全くない例ですが、たとえば、「対象を絞りたい」、「受注がなくてもすべての商品を出したい」、「受注数合計だけでなく、最大の受注数も出したい」などの追加要望があったときに、最も簡単に対応できるのはCASE3です。
まあ、これも大した手間の差ではないですけどね。

3つ目の見方は、「CASE2の書き方が状況次第では一番レスポンスがいい」です。先にグループするとJOINする件数が減るので、コストが下がります。基本的にはレスポンスのいい書き方といえます。
(商品を絞るときでも受注数のサブクエリに条件を追加することになるので、メンテナンス性はあまりよくないです)

ただ、状況次第と書いた理由は、以下の通りです。
・もし受注データが少ない場合は、このコストの差は極めて少ないので、体感できるほどのレスポンスの差はでないでしょう。
・もし受注データが非常に多い場合、Oracleのオプティマイザがどの書き方をしても、Case2の実行プランが一番早いと判断して、Case2のクエリに書き換えて実行するでしょう。

(オプティマイザはどのDBMSにもあるし、バージョンによって動きは違いますが、おそらく)

ということで、結局どの書き方でも私は問題ないという意見です。

投稿日時 - 2008-09-06 00:40:33

お礼

返信ありがとうございます。
詳しく記述いただきありがとうございます。
CASE1については、特に記述がなかったのですが、CASE3と同じとみてもいいのでしょうか?それとも多少なりともなにか変わるのでしょうか?教えてください

投稿日時 - 2008-09-07 11:35:49

あなたにオススメの質問