質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

4回答

4559閲覧

SQLで一つのテーブルでカウントした数を他のテーブルに引き算する方法

space_sss

総合スコア81

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2018/08/05 12:53

編集2018/08/05 13:24

商品の在庫管理をするシステムで一応問題なく動いてはいるのですが効率が悪いので改善を行いたく今回はご質問させていただきました。

商品リスト
|商品リストid|商品コード|商品名|在庫|サイズ|
|:--|:--:|--:|
|1| fruits01 |りんご|5|中|
|2| fruits01 |りんご|5|大|
|3| fruits02 |みかん|5|中|
|4| fruits03 |ぶどう|5|中|

仮押さえリスト

id商品リストid
12
23
33
41
53
63
73
81
91
101
111

上記のようなテーブルが二つ用意されています。
商品リストが商品の一覧となり仮押さえリストが商品リストIDに紐付いて一旦在庫を確保しています。
なので一旦確保され在庫が0になった場合は売り切れと表示を変更するようになっています。
ただサイズ違いは両方がなくならない限り在庫ありになります。

なので上記の結果としては
りんご在庫あり
みかん在庫なし
ぶどう在庫あり
となります。

希望の返り値は商品名、在庫で

商品名在庫
りんご4
みかん0
ぶどう5

となるのが理想です。

ですが現在はかなり無理矢理になっている気がしてもっと効率のいい方法があると思い今回質問させていただきました。
現在の状態は

sql

1SELECT 2 商品コード, 3 max(商品名) AS 商品名, 4 SUM(ifnull(在庫,0)) AS 在庫数 5FROM 6 商品リスト 7GROUP BY 8 商品コード
商品コード商品名在庫
fruits01りんご10
fruits02みかん
fruits03ぶどう

まず商品コードごとの在庫数を取得しています。
そのあとに仮押さえリストからCOUNTで取得します。
その際商品リストにJOINして商品コードを取得しています。

sql

1SELECT 2 T2.商品コード, 3 COUNT(*) AS cnt 4FROM 5 仮押さえリスト T1 6LEFT JOIN 7 商品リスト AS T2 8ON 9 T1.商品リストid = T2.商品リストid 10GROUP BY 11 T2.商品コード 12HAVING 13 (COUNT(*) > 0)
商品コード在庫
fruits016
fruits025
fruits030

この二つのSQLをなげてそのあとに
商品コードをが紐付いているので単純にphpで引き算をして画面に表示させています。

もしSQLのみでできる方法があればご教授願いたいのですがよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

一筆で書くならこんな感じ。

SQL

1select v1.商品コード, v1.商品名, 商品在庫 - coalesce(仮押さえ件数, 0) 2from ( 3 select 商品コード, 商品名, sum(在庫) as 商品在庫 4 from 商品リスト 5 group by 商品コード, 商品名 6 ) v1 left join ( 7 select 商品コード, count(*) as 仮押さえ件数 8 from 仮押さえリスト t1 inner join 商品リスト t2 9 on t1.商品リストid=t2.商品リストid 10 group by 商品コード 11 ) v2 12 on v1.商品コード=v2.商品コード

サブクエリーも似たような感じですけど、上記v2に対しての相関になるので、こちらの方がよさげな気がします。

投稿2018/08/05 15:19

sazi

総合スコア25195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自己解決

こちらで解決いたしました。

他にも意見がありましたら本日まで、ぜひお待ちしております。

sql

1SELECT 2 s.商品名 3 ,sum(ifnull(s.在庫,0) - ifnull(k.仮押さえ数,0)) 4FROM 5 商品リスト s LEFT JOIN ( 6 SELECT 7 商品リストid 8 ,count(商品リストid) AS 仮押さえ数 9 FROM 10 仮押さえリスト 11 GROUP BY 12 商品リストid 13 ) k ON s.商品リストid = k.商品リストid 14GROUP BY 15 s.商品名

投稿2018/08/05 14:59

space_sss

総合スコア81

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2018/08/06 01:34

普通にやるならこれでしょうね しかし問題は「商品リスト 」がマスターデータと在庫データの両方を兼ねていることです 在庫データは別テーブルで管理するとなぜこの方法になるかわかると思いますよ
space_sss

2018/08/06 02:32

コメントありがとうございます。 saziさんのやり方が商品在庫と商品リストが分かれているのでわかりやすいとも思ったのですがこちらを参考にしてそもそも在庫テーブルを分けて管理しJOINした方が整理されて良いのかなとも思いました。 やはりそちらの方が一般的なのでしょうか? お手数ではありますがご回答いただければ幸いです。
yambejp

2018/08/06 03:14

再質問の意図がわかりかねるのですが 単純に在庫データは頻繁に変動するデータで その他のマスターデータは基本的には変動しないデータということ それを同じテーブルで管理するのは本来のSQLのデータ管理とは 乖離があるということです。
guest

0

SQL

1SELECT 2 商品名, 3 Sum(在庫) - (SELECT COUNT(商品リストid) FROM 仮押さえリスト Where 商品リストid= Goods.商品リストid) AS 在庫 4 FROM 商品リスト GROUP BY 商品リストid, 商品名;

-- 修正

SQL

1CREATE TABLE 商品リスト 2(`商品リストid` int,`商品コード` nchar(10),`商品名` nchar(4),`在庫` int,`サイズ` nchar(2)); 3INSERT INTO 商品リスト VALUES 4( 1,' fruits01 ', 'りんご',5,'中' ) 5,( 2,' fruits01 ', 'りんご',5,'大' ) 6,( 3,' fruits02 ', 'みかん',5,'中' ) 7,( 4,' fruits03 ', 'ぶどう',5,'中' ); 8 9CREATE TABLE 仮押さえリスト 10(id int ,商品リストid int); 11INSERT INTO 仮押さえリスト VALUES 12( 1,2) 13,( 2,3) 14,( 3,3) 15,( 4,1) 16,( 5,3) 17,( 6,3) 18,( 7,3) 19,( 8,1) 20,( 9,1) 21,( 10,1) 22,( 11,1);

SQL

1SELECT 2 商品名, 3 Sum(在庫) - (SELECT COUNT(商品コード) FROM (SELECT 商品コード FROM 仮押さえリスト JOIN 商品リスト ON 仮押さえリスト.商品リストid = 商品リスト.商品リストid) AS T Where T.商品コード = 商品リスト.商品コード) AS 在庫 4 FROM 商品リスト GROUP BY 商品名;

投稿2018/08/05 13:51

編集2018/08/05 15:00
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

papinianus

2018/08/05 13:52

Create文とテストデータのinsert文をかいて。つらい。
space_sss

2018/08/05 14:09 編集

CREATE TABLE 商品リスト (商品リストid ,商品コード,商品名,在庫,サイズ); INSERT INTO 商品リスト VALUES ( 1,' fruits01 ', 'りんご',5,'中' ) ,( 2,' fruits01 ', 'りんご',5,'大' ) ,( 3,' fruits02 ', 'みかん',5,'中' ) ,( 4,' fruits03 ', 'ぶどう',5,'中' ); CREATE TABLE 仮押さえリスト (id ,商品リストid); INSERT INTO 仮押さえリスト VALUES ( 1,2) ,( 2,3) ,( 3,3) ,( 4,1) ,( 5,3) ,( 6,3) ,( 7,3) ,( 8,1) ,( 9,1) ,( 10,1) ,( 11,1); こちらでどうでしょうか?
space_sss

2018/08/05 14:27

上記の回答ですと商品IDごとに表示が出てしまうかと思うのですが.... りんご 0 りんご 4 みかん 0 ぶどう 5 と表示になってしまうかと思います。。。 一応希望としては りんご 4 みかん 0 ぶどう 5 でしたのでもしお手数でなければご回答いただければと思います。
papinianus

2018/08/05 15:03

できてたと思ってたってことはinsertのときに商品リストidを同じにしてたのかな。 修正しましたが、なんか面倒なクエリになってしまいました。
guest

0

まずは商品リストと仮押さえリストをidで結合して新しくできたリストを集計しましょう。

訂正2

商品リストと(商品リストid毎の仮押さえ数)を結合して集計。

SQL

1SELECT 2 s.商品名 3 ,sum(s.在庫 - k.仮押さえ数) 4FROM 5 商品リスト s JOIN ( 6 SELECT 7 商品リストid 8 ,count(商品リストid) AS 仮押さえ数 9 FROM 10 仮押さえリスト 11 GROUP BY 12 商品リストid 13 ) k ON s.商品リストid = k.商品リストid 14GROUP BY 15 s.商品名

投稿2018/08/05 13:51

編集2018/08/05 14:31
hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hichon

2018/08/05 14:00

おっと、質問を勘違いしていたので無視して下さい。
hichon

2018/08/05 14:18

訂正を追加しました。
hichon

2018/08/05 14:32

商品名毎に集計するように訂正。
space_sss

2018/08/05 15:01 編集

ご回答ありがとうございました! だいぶ参考になりました!ただこれですとぶどうが引き算した際にNULLになり落ちてしまうので一部修正させていただきました! ご回答ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問