• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:SQLの質問です。)

SQLで商品に対しての予約と受取の明細を集計する方法

このQ&Aのポイント
  • Oracle Database Express Editionを使用して、商品に対して予約と受取の明細を正確に集計するSQLを組みたいと思っています。商品TBL、予約TBL、明細TBLの3つのテーブルを使用し、予約数、予約明細数、受取数、受取明細数を出力する結果を得たいです。
  • 現在実行しているSQLでは予約明細数と受取明細数が正しく計算されず、結果が間違っています。どこが間違っているのか分からず困っています。解決策や修正方法を教えていただけると助かります。
  • SQLの実行結果では、商品ごとに予約数と受取数は正しく集計されていますが、予約明細数と受取明細数は正しく計算されていません。予約明細数と受取明細数を正確に集計するためにはどのような修正が必要なのでしょうか?

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

  • ベストアンサー
  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.1

select a.a1,count(b.a1),count(c.a1) from a,b,c where a.a1 = b.a1(+) and a.a1 = c.a1(+) group by a1 でcount(b.a1)とcount(c.a1)の値がどのようにでてくるかの理解が違っています。 ★a.a1 1 2 3 ★b.a1,a2 1,101 1,102 2,201 ★c.a1,a3 2,222 3,333 3,444 というデータになっていると、 select a.a1,b.a1,b.a2,c.a1,c.a3 from a,b,c where a.a1 = b.a1(+) and a.a1 = c.a1(+) は、 a.a1,b.a1,b.a2,c.a1,c.a3 1,1,101,, 1,1,102,, 2,2,201,2,222 3,,3,333 3,,3,444 となります。 で、 select a.a1,count(b.a1),count(c.a1) from a,b,c where a.a1 = b.a1(+) and a.a1 = c.a1(+) group by a1 は、 1,2,2 2,1,1 3,2,2 となります。 b.a1やc.a1がNullであろうが値が入っていようが、1件としてカウントされます。 select a.a1,sum(case b.a1 isnull then 1 else 0 end) ,sum(case c.a1 isnull then 1 else 0 end) from a,b,c where a.a1 = b.a1(+) and a.a1 = c.a1(+) group by a1 なんてしたら、 1,2,0 2,1,1 3,0,2 とでてきます。 方法1:がんばってこれでやってみる。 select shohin.shohin_no as "商品NO" ,sum(case when yoyaku_1.shohin_no is null then 0 else 1 end) as "予約数" ,sum(case when receipt_1.shohin_no is null then 0 else 1 end) as "予約明細数" ,sum(case when yoyaku_2.shohin_no is null then 0 else 1 end) as "受取数" ,sum(case when receipt_2.shohin_no is null then 0 else 1 end) as "受取明細数" from shohin ,(select * from yoyaku where yoyaku.status = '1') yoyaku_1 ,(select * from yoyaku where yoyaku.status = '2') yoyaku_2 ,(select * from receipt where receipt.status = '1') receipt_1 ,(select * from receipt where receipt.status = '2') receipt_2 where yoyaku_1.shohin_no(+) = shohin.shohin_no and yoyaku_2.shohin_no(+) = shohin.shohin_no and receipt_1.shohin_no(+) = yoyaku_1.shohin_no and receipt_1.status(+) = yoyaku_1.status and receipt_2.shohin_no(+) = yoyaku_2.shohin_no and receipt_2.status(+) = yoyaku_2.status group by shohin.shohin_no order by 1 どう考えても処理遅そう。 方法2:group by した結果を結合する。 select shohin.shohin_no as "商品NO" ,nvl(yoyaku_1.cnt,0) as "予約数" ,nvl(receipt_1.cnt,0) as "予約明細数" ,nvl(yoyaku_2.cnt,0) as "受取数" ,nvl(receipt_2.cnt,0) as "受取明細数" from shohin ,(select shohin_no,count(*) as cnt from yoyaku where yoyaku.status = '1' group by shohin_no) yoyaku_1 ,(select shohin_no,count(*) as cnt from yoyaku where yoyaku.status = '2' group by shohin_no) yoyaku_2 ,(select shohin_no,count(*) as cnt from receipt where receipt.status = '1' group by shohin_no) receipt_1 ,(select shohin_no,count(*) as cnt from receipt where receipt.status = '2' group by shohin_no) receipt_2 where yoyaku_1.shohin_no(+) = shohin.shohin_no and yoyaku_2.shohin_no(+) = shohin.shohin_no and receipt_1.shohin_no(+) = shohin.shohin_no and receipt_2.shohin_no(+) = shohin.shohin_no group by shohin.shohin_no order by 1 注:nvl(yoyaku_1.cnt,0)は、yoyaku_1.cntがNull(対象商品がない)時に0を表示します。   方法3:スカラー副問い合わせを使う。 select shohin.shohin_no as "商品NO", (select count(*) from yoyaku where yoyaku.status = '1' and yoyaku.shohin_no = shohin.shohin_no ) as "予約数", (select count(*) from receipt where receipt.status = '1' and receipt.shohin_no = shohin.shohin_no ) as "予約明細数", (select count(*) from yoyaku where yoyaku.status = '2' and yoyaku.shohin_no = shohin.shohin_no ) as "受取数", (select count(*) from receipt where receipt.status = '1' and receipt.shohin_no = shohin.shohin_no ) as "受取明細数" from shohin order by 1 ※receiptはshohinと結合すべきでないのかもしれませんが、  あってはいけないyoyakuと結合できないreceiptは  (質問のようにyoyakuとreceiptを結合するとカウントされないが、   この回答ではカウントされてしまう。)  質問に示された【想定結果】では調べようがないので、  別途調べるselect文を実行するだろうから、手っ取り早く、  shohinと結合してしまいました。 ## 大量データを投入して、全部動かしてみてどれが早いか試してみるのも、 ## 勉強のうちなのかも。

nick_555
質問者

お礼

こんな時間に素早いご回答、感謝します! 解説もとてもわかりやすかったです。 まず1回グループ化する前の全体像を把握すべきだったのですね。 また、改善案を3つも書いて頂き、本当にありがとうございます。 試してみたところ、しっかり想定通りの結果が出ました。 (方法1はうまくいきませんでしたが…これは自分で確かめてみます!) 大量データは、ちょっと今日はもう遅いので、明日明後日辺りに試してみたいと思います。 これで今日はぐっすり眠れそうです(笑) 本当にありがとうございました。

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.2

そもそも明細TBLに予約TBLとの関連がないのが良くないと思うのですが。 それがあればもっと単純なSQLでよくなるはずです。

nick_555
質問者

お礼

自分で勉強用にこんな感じかなぁと思って作成したものでしたので、未熟なのは分かっていましたが…なるほど、テーブルを見直すという選択肢もあるのですね。 今後の参考にさせて頂きます。 ご指南、ありがとうございました!

すると、全ての回答が全文表示されます。

関連するQ&A