売上管理についての質問

このQ&Aのポイント
  • ネットショップの売上一覧表示のために、複数のテーブルを結合して伝票番号毎の合計金額を求めたいが、うまくいかない。
  • 現在のテーブル構成での結果を得ることができないため、適切なSQL文のアドバイスを求めています。
  • 初めて作成したテーブル構成で、もっと効率的な方法があればアドバイスをお願いしたい。
回答を見る
  • ベストアンサー

売上管理

お世話になっております。 勉強がてらネットショップを作っているのですが、売上一覧を表示すべくところで立ち止まってしまいました。 以下にテーブルの構成および得たい結果を書き残しますので、ご教示頂けた幸いです。(MySQL5) テーブル名:member member_no  name1  1      佐藤  2      小島  3      石田  4      鈴木 テーブル名:sales sales_no sale_slip_no sales_date  member_no goods_name request_money receipt_maney  1     1     2013-6-6     2     キュウリ      5250  2     1     2013-6-6     2     イチゴ       3150  3     1     2013-6-6     2     バナナ       8400  4     2     2013-6-7     1     りんご       5250  5     2     2013-6-7     1                         3000  6     3     2013-6-8     4     ほうれん草     9450  7     3     2013-6-8     4     しいたけ      2100  8     4     2013-6-8     3     マンゴー      6300 ・各テーブルにあるmember_noカラムは対となる紐付くデータです。 ・sale_slip_noは伝票番号です。 ・request_moneyは商品単位での小計金額です。 ・receipt_maneyは入金金額(またはポイントが支払いに使われた時の金額)です。 ・質問と無関係と思われるカラムは省略しています。 以上のような構成のテーブルがありますが、以下のように伝票番号毎に別け、かつ伝票毎の合計額を求めたいと考えています。 sale_slip_no sales_date  name  request_money  4      2013-6-8   石田    6300  3      2013-6-8   鈴木    11550  2      2013-6-7   佐藤    2250  1      2013-6-6   小島    16800 以上ですが、join group sumの組み合わせになるのかな・・と考え調べ、試行錯誤を繰り返していますが、描いている結果を得ることが出来ません。どのようなSQLになるのかご教示いただければ幸いです。 また、売上データとして蓄積させるテーブル構成を作ったのは初めてですが、もっと適切なものがあれば、こちらも併せてアドバイスを頂けると幸いです。 お忙しいなか恐縮ですが、宜しくお願い申し上げます。

  • MySQL
  • 回答数5
  • ありがとう数5

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.4

#3です たとえばこんな感じで検討してみてはどうでしょうか? テーブル、member=販売先管理テーブル,slip=伝票管理テーブル,sales=売上集計テーブル create table member(member_no int,name varchar(20),index(member_no,name)); insert into member values(1,'佐藤'),(2,'小島'),(3,'石田'),(4,'鈴木'); create table slip (slip_no int,member_no int,sales_date date,index(slip_no,member_no,sales_date)); insert into slip values(1,2,'2013-06-06'),(2,1,'2013-06-07'),(3,4,'2013-06-08'),(4,3,'2013-06-08'); create table sales(sales_no int,sale_slip_no int,goods_name varchar(30) null,request_money int null,receipt_money int null,index(sale_slip_no,request_money,receipt_money)); insert into sales values(1,1,'キュウリ',5250,null),(2,1,'イチゴ',3150,null),(3,1,'バナナ',8400,null),(4,2,'りんご',5250,null),(5,2,null,null,3000),(6,3,'ほうれん草',9450,null),(7,3,'しいたけ',2100,null),(8,4,'マンゴー',6300,null); //販売一覧を表示 select sales_no,sale_slip_no,sales_date,member_no,goods_name,request_money,receipt_money from sales as t1 left join slip as t2 on t1.sale_slip_no=t2.slip_no //集計 select t1.sale_slip_no,t2.sales_date,t3.name,ifnull(sum(request_money),0)-ifnull(sum(receipt_money),0) as request_mony from sales as t1 left join slip as t2 on t1.sale_slip_no = t2.slip_no left join member as t3 on t2.member_no = t3.member_no group by sale_slip_no

a4_chapp
質問者

お礼

yambejpさま こんばんは。お世話になっております。 実際にSQLまでご提示頂き感謝です。ありがとうございます! yambejpさまのテーブル構成、拝見いたしました。 確かに、見た目だけではなく、売上内容と伝票データを別にすることで、整った形かと思います。見ていてうなずけました。 yambejpさまご提示の3種のテーブルをみると、顧客情報、伝票情報、売上詳細の3種になっていますが、この売上詳細である、salesを見ると、当初の私の質問時に書いたsalesと比較し、sales_date、member_noを省略し、sales_slip_noで紐付けることが出来る、というのが分かります。 そこで、勉強のつもりで、恥を承知で改めて質問させて下さい。 (教えて君のようで恐縮なのですが)今回の私の質問にある、伝票番号毎の合計(入金も含む)を集計するにはどのようなSQLになるのか、お教え頂くことは可能でしょうか? 今回の伝票番号単位での集計だけであれば、今回私が質問時に提示した構成でも問題はなさそうですが、売上詳細を含まない集計まで視野に入れると、やはりyambejpさまご提示構成の方が適切だろうな...という考えに至っていますが、3つのテーブルを結合しての集計処理に、今回の質問以上に難しく思えてしまって... 恐れ入ります。お忙しい中恐縮ですが引続きアドバイスを頂戴出来れば幸いです。 宜しくお願い申し上げます。

その他の回答 (4)

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.5

>今回の私の質問にある、伝票番号毎の合計(入金も含む)を集計する 私の認識が間違っていたら申し訳ないですが それって私の書いた「集計」のSQLだと思うのですがちがいます?

a4_chapp
質問者

お礼

yambejpさま すみません!!!!!! create文とテーブル構成ばかりに気持ちが傾いていたので、一緒にご提示頂いた、一覧、集計のSQLのことすっかり忘れていました!! 本当に申し訳ありません! で、結果は期待している結果を得ることが出来ました! yambejpさまのいう正規化を改めて考える切っ掛けになりました。 ユニークな数値が割り当てられたら、テーブルは分割し簡素化した方が宜しいのですね。 今回改めて勉強になりました。 感謝いたします。ありがとうございました!

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

正規化が中途半端 sale_slip_noに対してsales_dateやmember_noがユニークに確定するなら 別テーブルで管理した方がいい そうすればSQL文も格段に簡略化できます。

a4_chapp
質問者

お礼

yambejpさま こんばんは。お世話になっております。 正規化が中途半端、別テーブルにした方が良いとのこと、 貴重なアドバイスをありがとうございます! 質問にある、salesテーブルをもっと分解した方が良いと仰っているのだろうと 認識していますが、改めてテーブル構成を考えているものの、分解しようも、 また同じような構成になってしまう・・と、こんなことを繰り返しています。 yambejpさまが仰るテーブルとはどんな構成でしょうか? アドバイスを頂けると幸いです。 宜しくお願い申し上げます。

回答No.2

select sale_slip_no,max(sales_date),name1 ,sum(coalesce(request_money,0)-coalesce(receipt_maney,0)) as request_money from sales inner join member on member.member_no=sales.member_no group by sale_slip_no,name1 order by 1 desc です。

a4_chapp
質問者

お礼

nharasawaさま こんばんは。貴重なアドバイスをありがとうございます。 試したところ、描いていた結果を得ることが出来ました! はじめてみるSQLでとても勉強になります。ありがとうございます!

  • Picosoft
  • ベストアンサー率70% (274/391)
回答No.1

手元にMySQLの環境がないのでAccessでしか試していませんが、 SELECT sale_slip_no, sales_date, name1 AS name, SUM(request_money) AS request_money FROM sales A LEFT JOIN member B ON A.member_no=B.member_no GROUP BY sale_slip_no, sales_date, name1 ORDER BY sale_slip_no DESC という感じでどうでしょうか?

a4_chapp
質問者

お礼

Picosoftさま こんばんは。質問投稿後、早速のアドバイスをありがとうございました! アドバイスを頂戴したSQLを試す環境でなかったため、お返事が遅れてしまいました。申し訳ありません。 結果を申し上げると、先ほど試したところ加算すべき金額の合計は出ましたが、入金などの減算すべき金額は反映されていませんでした。 MySQLの環境がない中でのアドバイス、ありがとうございます!

関連するQ&A

  • 4つのテーブルで構成される売上データをまとめたい

    お世話になっております。4つのテーブルの結合について質問させて下さい。(MySQL5) データベースの内容は販売に関するもので、以下のような4つのテーブルがあります。(不必要なカラムは省略しています) テーブル名:goods(商品 goods_no | goods_name 1       りんご 2       みかん 3       いちご テーブル名:member(顧客データ) member_no | member_name 1          鈴木 2          佐藤 3          小林 4          斉藤 テーブル名:slip(伝票番号) slip_no|sales_member_no|sales_date 1       2        2013-6-1 2       4        2013-6-1 3       1        2013-6-2 4       3        2013-6-3 ※slip.sales_member_no = member.member_noです。 テーブル名:sales(売上から入金までのデータを時系列で登録) sales_no|sale_slip_no|sales_goods_no|sales_goods_price|sales_goods_cnt|request|receipt 1       1         2       350        5      1750 2       1         3       400        3      1200 3       2         1       200        5      1000 4       2         3       400        4      1600 5       1        receipt                              2950 6       2        receipt                              2600 7       3        1       200        8      1600 8       4        2       350        5      1750 9       3        receipt                              1600 10       4        receipt                              1750 ※sales.sale_slip_no=slip.slip_noです。 sales.sales_goods_no=goods.goods_noです。 以上のようなテーブルがあり、4つのテーブルを結合して、 伝票単位で、売上詳細(sales)、商品名(goods)、顧客名(member)を以下のように伝票番号順で一覧で表示したいと考えていますが、エラーだったり、期待している結果を得ることが出来ません。 どのようにすれば宜しいのかアドバイスのほど頂戴出来れば幸いです。 slip_no  商品名 個数 単価  請求額 入金額 1     みかん  5   350  1750 1     いちご  3   400  1200 1                         2950 2     りんご  5   200  1000 2     いちご  4   400  1600 2                         2600 3     りんご  8   200  1600 3                         1600 4     みかん  5   350  1750 4                         1750 以上、お忙しい中恐縮ですが、宜しくお願い申し上げます。

  • MySQLでの売上集計

    お世話になっております。MySQLのSQLに関する質問ですが、変数で処理しているため、PHPカテゴリで質問させて下さい。 テーブル:slip slip_no  member_no  sales_date 1      2      2013-06-06 2      1      2013-06-07 3      4      2013-06-08 4      3      2013-06-08 テーブル:sales sales_no  sale_slip_no  goods_no  goods_name  request_money  receipt_money 1       1        2      キュウリ    5250        NULL 2       1        3      イチゴ     5250        NULL 3       2        6      バナナ     5250        NULL 4       2        5      りんご     5250        NULL 5       2        point    NULL      NULL        3000 6       3        1      ほうれん草   9450        NULL 7       3        4      しいたけ    2100        NULL 8       4        7      マンゴー    6300        NULL このようなテーブルがあります。(MySQL5) slip_noとsale_slip_noは紐付くデータで、slipテーブルにあるmember_no毎に、 salesテーブルのgoods_noが整数を条件に、request_moneyの1ヵ月前の期間内の request_moneyの合計を算出したいと考えております。 member_no 1を呼出したら、 total 10500 とこのように算出。 以前、http://okwave.jp/qa/q8117105.html こちらで、ご親切に回答頂き、解決したのですが、このテーブルに関連する質問を http://okwave.jp/qa/q8126398.html こちらで伺ったところ、ご親切に正規化を指摘され、テーブルを上記のように分割したという経緯が御座います。 以上のことから、 http://okwave.jp/qa/q8117105.html でアドバイス頂いたSQLを元に、inner join を用いて以下のようなSQLを試していますが、得たい結果を得ることが出来ません。 直接関係ないかもしれませんが、FROMの前にmember_noやsale_slip_no、slip_noなどのカラムを記述するとエラーになったりで、かれこれ3時間もこのSQLで格闘しています。 $sql = "SELECT SUM(request_money) FROM sales INNER JOIN slip ON sales.sale_slip_no = slip.slip_no WHERE slip.member_no = '1' AND sales.goods_no REGEXP '^[0-9]+$' AND slip.sales_date between curdate() - interval 1 month + interval 1 day AND curdate()"; $result = mysql_query($sql); $sum_point = mysql_fetch_assoc($result); $one_month_buy_money = $sum_point['SUM(request_money)']; 最近、質問ばかりで恐縮ですが、アドバイスのほど頂戴出来ればと質問させて頂きました。 お忙しい中恐縮ですが、宜しくお願い申し上げます。 .

    • ベストアンサー
    • PHP
  • 【IT関連】 テーブルの英語表現を教えて下さい

    これらの英単語、英訳が見当もつきません。 ぜひ教えてください。一応英訳は自分で作ってみました。 (テーブル名等が固有名詞でないのは、一般的なものとして話したいからです) 1.販売伝票テーブルと販売明細テーブルで、販売伝票番号と販売明細(番号)をキーにしてつきあわせる match a table sales document and a table sales slip with keys sales number and sales slip number. 2.(あるテーブルの)勘定コードが1234であるものの削除フラグをたてる make the soft delete flag of accounting code '1234' make the soft delete flag on whose accounting code is '1234'

  • テーブル結合方法について

    MySQL5.1で、Table a ,Table b から、Table cのように取り出したいのですが、 SQLでSELECTする方法がわかりません。 Table b優先だけど、Table aにしかデータがない場合もあるといった感じです。 Table a No  Name 1 加藤 2 佐藤 3 田中 Table b No Name 2 佐藤先輩 4 田辺先輩 Table c No Name 1 加藤 2 佐藤先輩 3 田中 4 田辺先輩 どうか、よろしくお願いします。

    • ベストアンサー
    • MySQL
  • テーブルを別ける判断要素をお聞かせ下さい

    お世話になっております。データベースのテーブルの別け方について質問させて下さい。 例えば、会員制のブログサービスを公開するとして、各会員の個人情報を収めるmemberというテーブルを以下のような構成で用意したとします。 (idはURLの一部となるもの) no  id   mail   pass  name  blog_title 1  lala ***@***.com 1234  佐藤  私の日記帳 2  tecno **@***.com 5432  石田  明日は何処へ 3  nonno **@***.com 9812  毛利  音楽大好き 上記は、会員の個人情報と併せ、ブログのタイトルなども1レコードで済むことが出来るので、会員情報とブログの情報も登録したケースです。 対して、以下は会員情報とブログ情報を別けた場合です。 memberテーブル no  mail   pass  name 1 ***@***.com 1234  佐藤 2 **@***.com  5432  石田 3 **@***.com  9812  毛利 blog詳細テーブル(member_noとnoで紐付けている) no member_no id   blog_title 1  1    lala  私の日記帳 2  3    nonno 音楽大好き 3  2    tecno 明日は何処へ 例えばhttp://blog.sample.com/lala/ というURLにアクセスされた場合、1つのテーブルに情報が収められている場合、個人情報が登録されたテーブルに接続しなければなりませんが、ブログ情報だけを別にしたテーブルを設けていると、個人情報が登録されたテーブルには接続しなくても済むかと思います。 ここで質問させて下さい。 以前、1つのレコードで収まるなら、複数のテーブルを用意する必要はないといった意見を聞いたことがあるのですが、上記のような2つのケースの場合、やはり貴重な情報を含まれたテーブルは、極力、接続機会を減らす方が良いのでしょうか? 今日まで、1つのレコードで収まるなら複数のテーブルは用意することなく来ましたが、もしかして、 ・2つのテーブルに別けようが、1つが漏洩したら全て漏洩したと同じだ。だから1つにまとめて問題ない。 ・貴重なテーブルは接続機会を減らすべきだ。 というような意見があるのでは?と、意見を伺えればと思い、質問させて頂きました。 お忙しいとは思いますが、ご意見のほど宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • 結合について

    次のようなテーブルがあるとします。 Table A No,Date,member_A,member_B 1 ,0102 ,1001 ,1003 2 ,0212 ,1091 ,1023 3 ,0403 ,1056 ,1065 Table B member ,Name 1001 ,Taro 1002 ,Takashi 1003 ,Yutaka といった具合のテーブルがあるとします。 やりたい事はTable AのNoを指定されたらDateとmember_Aとmember_BのNameを取得したいのです。 例えば、No1を指定したら、0102 ,Taro ,Yutakaといった具合に・・・。1発で取得するにはどういったSQLになりますか?どなたかご教授願います。よろしくお願いします。

  • テーブルの結合について教えてください。

    テーブルの結合についてわからなくなってしまったので、教えてください。 次のようなテーブルがあります。 counterテーブル ・page_no ・cnt pageテーブル ・no ・member_no linkテーブル ・page_no ・member_no memberテーブル ・no ・name ・flag 各ページにカウンタがついている。 各ページは作成したメンバが記録されている 各ページにはリンクがはられてあり、そのリンクを作成したメンバが記録されている。 各メンバには、退会を示すflagがあり、flag=0が会員、flag=1が退会を示す。 以上のような条件で、 退会していないメンバが関係するページのnoとカウンタの値を取得したい (関係とは、メンバが作ったorリンクを貼った という意味です) のですが、どのように記述すればよいのでしょうか? 自力で考えようとしたのですが、力尽きました。 すみませんが、ご教授お願いいたします。

    • ベストアンサー
    • MySQL
  • GROUP BYについて

    お世話になっております。GROUP BY に関してつまずいています。 色々と調べているのですが、解決できないため質問させて下さい。 まず下記のような履歴テーブルがあります。 rireki_member_noとは投稿者のIDであり、title1、title2に登録された日付データ(date型)は その投稿者が投稿した日付が登録されています。(title1だけの場合もあればtitle2だけの場合もあり、両方の場合もあります) rirekiテーブル rireki_no rireki_member_no  title1     title2  1       2       2014-09-12   2       1                 2014-09-12  3       3       2014-09-14   2014-09-14  4       2       2014-09-18  5       1                 2014-09-19 また、下記は投稿者のテーブルであり、rireki_member_noと、member_noは紐付いたものとなります。 memberテーブル memner_no  member_name  1       佐藤  2       吉田  3       佐々木 そこで今回行いたいのは、タイトルを指定し、且つ日付を範囲指定した時、その会員の名前、そして投稿した日付を一覧で表示したいと考えていますが、その際のSQL文が分からず困っている状況です。 イメージ的には、 title2を指定し、2014-9-13から20149-19と範囲指定した場合 3  佐々木  2014-09-14 2  吉田   2014-09-19 といった結果を求めたいと考えています。 お恥ずかしいとは思いますが、実は昨夜からずっと悩んでいたりして・・・ rirekiテーブル単体であれば、 http://norm-nois.com/blog/archives/1293 で似たような内容で紹介されているのですが、今回のようにJOINが絡むと難易度が高くなっている状況です。 お忙しいなか恐縮ですが、お知恵を頂戴出来れば幸いです。 宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • SQLの質問です。

    Oracle Database Express Editionを使って勉強中の者です。 商品TBL、予約TBL、明細TBLと3つのテーブルを使用して、商品に対して予約と受取の明細がきちんと出ているのか、件数を出すSQLを組みたいと思っています。 例えば、 【商品TBL:shohin】 shohin_no / shohin_nm / price ----------------------------- s001 / name1 / 1000 s002 / name2 / 1500 s003 / name3 / 2000 【予約TBL:yoyaku】 yoyaku_no / shohin_no / status(1:予約, 2:受取) ----------------------------- y001 / s001 / 1 y001 / s001 / 2 y002 / s001 / 1 y002 / s002 / 1 y002 / s002 / 2 【明細TBL:receipt】 shohin_no / status / receipt ----------------------------- s001 / 1 / abc.. s001 / 2 / def.. s002 / 1 / ghi.. 【想定結果】 商品NO / 予約数 / 予約明細数 / 受取数 / 受取明細数 ----------------------------- s001 / 2 / 1 / 1 / 1 s002 / 1 / 1 / 1 / 0 s003 / 0 / 0 / 0 / 0 としたいのですが、どうにも上手くいかず、下記のような結果が返ってきます。 【結果】 商品NO / 予約数 / 予約明細数 / 受取数 / 受取明細数 ----------------------------- s001 / 2 / 2 / 2 / 2 s002 / 1 / 1 / 1 / 0 s003 / 0 / 0 / 0 / 0 私が実行したSQLは下記です。 恐らく何か初歩的な所で間違っているような気がするのですが、自分では分からず…。 一体何がいけないのか、ご教授の程、よろしくお願い致します。 select shohin.shohin_no as "商品NO" ,count(yoyaku_1.shohin_no) as "予約数" ,count(receipt_1.shohin_no) as "予約明細数" ,count(yoyaku_2.shohin_no) as "受取数" ,count(receipt_2.shohin_no) as "受取明細数" from shohin ,(select * from yoyaku where yoyaku.status = '1') yoyaku_1 ,(select * from yoyaku where yoyaku.status = '2') yoyaku_2 ,receipt receipt_1 ,receipt 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

  • 出欠登録について

    現在phpとデータベースにて出欠登録を作成しています。 データベースには メンバーのテーブル、スケジュールのテーブル、出欠登録用のテーブルがあります。 $schedule_id = $_GET["scheduleno"]; $memberquery = sprintf("SELECT * FROM `member`"); $schedulequery = sprintf("SELECT * FROM `schedule` WHERE `scheduleno`='$schedule_id'"); $entryquery = sprintf("SELECT * FROM `entry` LEFT JOIN `member` ON `member_id`=member.no WHERE `schedule_id`='$schedule_id' AND `member_id`='$member_id'"); memberテーブル | no | 名前 | | 1 | 佐藤 | | 2 | 鈴木 | | 3 | 渡辺 | scheduleテーブル | no | 日程 | | 1 | 2011-01-23 | | 2 | 2011-01-30 | entryテーブル | no | schedule_id | member_id | entry | | 1 | 1 | 1 | 1 | | 2 | 1 | 2 | 2 | としてり、 出席者を割り出すには $entryquery1 = sprintf("SELECT * FROM `entry` LEFT JOIN `member` ON `member_id`=member.no WHERE `schedule_id`='$schedule_id' AND `entry` = 1"); 欠席者を割り出すには $entryquery2 = sprintf("SELECT * FROM `entry` LEFT JOIN `member` ON `member_id`=member.no WHERE `schedule_id`='$schedule_id' AND `entry` = 2"); としています。 ここで質問なのですが、出席者や欠席者は取得できていますが、未登録者を取得ができず困っています。 例 出席者 佐藤 欠席者 鈴木 未登録者 渡辺 としたいが、未登録者 渡辺がだせない。 どなたか仕組みを教えていただけないでしょうか? また、ソースも教えていただけれると助かります。

    • ベストアンサー
    • PHP