• ベストアンサー

PHP+MySQLで月ごとの数量を表示したい

MySQLに以下のような形でデータが入っています。 連番|販売日|商品名|単価|数量 1|2014/01/15|たわし|100|5 2|2014/02/10|スポンジ|50|2 3|2014/03/05|タオル|200|3 ・・・ このようなデータが大量に保存されていて、それをPHPで以下のように出力したい場合 (数量でも合計金額でも) 2013年度 商品名|4月|5月|6月|・・・12月|1月|2月|3月|合計 たわし|5|6|12|・・・7|14|21|15|210 スポンジ|・・・ どのようにデータを抽出し、どのように表示すればよいでしょうか?

  • PHP
  • 回答数4
  • ありがとう数4

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

  • ベストアンサー
  • agunuz
  • ベストアンサー率65% (288/438)
回答No.3

アプローチは二つあります。 (1)SQL文で集計して集計結果をphpで受け取って処理する 集計したい開始年月と終了年月が既知であれば、手っ取り早い方法です。 下記ソースではリテラルで書いていますが、phpスクリプトで動的に生成すればいいですね。 $sql = <<<EOD select `商品名`, sum(if (date_format(`販売日`, '%Y%m')='201401', `数量`, 0)) as `1月`, sum(if (date_format(`販売日`, '%Y%m')='201402', `数量`, 0)) as `2月`, sum(if (date_format(`販売日`, '%Y%m')='201403', `数量`, 0)) as `3月`, sum(if (date_format(`販売日`, '%Y%m')='201404', `数量`, 0)) as `4月`, sum(if (date_format(`販売日`, '%Y%m')='201405', `数量`, 0)) as `5月`, sum(if (date_format(`販売日`, '%Y%m')='201406', `数量`, 0)) as `6月`, sum(if (date_format(`販売日`, '%Y%m')='201407', `数量`, 0)) as `7月`, sum(if (date_format(`販売日`, '%Y%m')='201408', `数量`, 0)) as `8月`, sum(if (date_format(`販売日`, '%Y%m')='201409', `数量`, 0)) as `9月`, sum(if (date_format(`販売日`, '%Y%m')='201410', `数量`, 0)) as `10月`, sum(if (date_format(`販売日`, '%Y%m')='201411', `数量`, 0)) as `11月`, sum(if (date_format(`販売日`, '%Y%m')='201412', `数量`, 0)) as `12月` from data group by `商品名` EOD; $stmt = $pdo->query($sql); // あくまでも「例」なので一気に読み込んでみます(汗 // 実際の出力は、この取得内容から勘案してください $arr = $stmt->fetchAll(PDO::FETCH_ASSOC); print '<pre>'; print_r($arr); print '</pre>'; (2)順次読み込んだデータをphpで集計する 集計範囲が決まっていなくてもいいです。「キーブレーク処理」に慣れていればさほど面倒ではありませんが、速度的に劣ると思います(集計はMySQLに任せた方がphpよりも速い)。 $stmt = $pdo->query("select *, date_format(`販売日`, '%Y%m') as yymm from data order by `商品名`"); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $yymm = $row['yymm']; if (isset($svhin)&&$svhin === $row['商品名']) { // 同じ商品だったら if (isset($svarr[$yymm])) { $svarr[$yymm] += $row['数量']; } else { $svarr[$yymm] = $row['数量']; } } else { // キーブレーク if (isset($svhin)) { print $svhin . '<br>'; // このprint部分は「決まっている年月範囲」があるときはそれに合わせて行う foreach ($svdat as $key=>$val) { printf('%s --- %d<br>', $key, $val); } } $svhin = $row['商品名']; $svdat = array(); $svdat[$yymm] = $row['数量']; } } if (isset($svhin)) { print $svhin . '<br>'; foreach ($svdat as $key=>$val) { printf('%s --- %d<br>', $key, $val); } }

ok-rjak
質問者

お礼

思った挙動になりました。 丁寧にありがとうございます。 PHPで集計する方法は、一度やってみたのですが、データが多くて表示に時間がかかったので、SQLで可能な方法を模索していました。 ちなみに、1月、2月と抽出していますが、12月のあとに1~12月の合計を表示する場合はどうすればいいでしょうか? sum(…)+sum(…)+・・・とやっていると効率が悪いですよね。せっかく1月、2月とラベルがあるのを使うことはできないのでしょうか?

その他の回答 (3)

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

>12月のあとに1~12月の合計を表示する場合 あれ?スクールカレンダーじゃないの? #3さんのロジックを使うのであれば //1~12月 sum(if (date_format(`販売日`, '%Y')='2014', `数量`, 0)) as `合計` //4~翌3月 sum(if (date_format(`販売日`, '%Y%m') BETWEEN '201304' AND '201403', `数量`, 0)) as `合計` pivotを使っていれば、データの絞り込みがすでにできているので sum(`数量`) as `合計` をつければ大丈夫です

ok-rjak
質問者

お礼

本来はスクールカレンダーですが、どちらでも聞けば応用できるかなと思いまして(笑) 答えを提示していただけると単純なことでしたが、助かりました。 pivotもこれから使えるようになっていきます。 ありがとうございました。

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

こういう集計はピボットテーブルというのをつくると楽です。 //pivot作成 create table pivot (mindate date,maxdate date,`4月` tinyint not null,`5月` tinyint not null,`6月` tinyint not null,`7月` tinyint not null,`8月` tinyint not null,`9月` tinyint not null,`10月` tinyint not null,`11月` tinyint not null,`12月` tinyint not null,`1月` tinyint not null,`2月` tinyint not null,`3月` tinyint not null); //データ投入 insert into pivot(mindate,maxdate,`4月`) values((@d:='2013-04-01') ,(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`5月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`6月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`7月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`8月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`9月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`10月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`11月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`12月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`1月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`2月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); insert into pivot(mindate,maxdate,`3月`) values((@d:=@d+interval 1 month),(@d+interval 1 month - interval 1 day),1); //内容確認 select * from pivot; 1が右肩下がりで投入されているのがわかります。 //元データ作成,データ投入 create table tbl(販売日 date,商品名 varchar(30),単価 int,数量 int); insert into tbl values('2014/01/15','たわし',100,5)('2014/01/20','たわし',100,10)('2014/02/1','たわし',100,7),('2014/02/10','スポンジ',50,2),('2014/03/05','タオル',200,3); ここから本題 //各月の品目の件数を表示 select 商品名 ,sum(`4月`) as `4月` ,sum(`5月`) as `5月` ,sum(`6月`) as `6月` ,sum(`7月`) as `7月` ,sum(`8月`) as `8月` ,sum(`9月`) as `9月` ,sum(`10月`) as `10月` ,sum(`11月`) as `11月` ,sum(`12月`) as `12月` ,sum(`1月`) as `1月` ,sum(`2月`) as `2月` ,sum(`3月`) as `3月` from tbl inner join pivot on 販売日 between mindate and maxdate group by 商品名; //各月の品目ごとの数量を表示 select 商品名 ,sum(`4月`*`数量`) as `4月` ,sum(`5月`*`数量`) as `5月` ,sum(`6月`*`数量`) as `6月` ,sum(`7月`*`数量`) as `7月` ,sum(`8月`*`数量`) as `8月` ,sum(`9月`*`数量`) as `9月` ,sum(`10月`*`数量`) as `10月` ,sum(`11月`*`数量`) as `11月` ,sum(`12月`*`数量`) as `12月` ,sum(`1月`*`数量`) as `1月` ,sum(`2月`*`数量`) as `2月` ,sum(`3月`*`数量`) as `3月` from tbl inner join pivot on 販売日 between mindate and maxdate group by 商品名; //各月の品目ごとの金額を表示 select 商品名 ,sum(`4月`*`数量`*`単価`) as `4月` ,sum(`5月`*`数量`*`単価`) as `5月` ,sum(`6月`*`数量`*`単価`) as `6月` ,sum(`7月`*`数量`*`単価`) as `7月` ,sum(`8月`*`数量`*`単価`) as `8月` ,sum(`9月`*`数量`*`単価`) as `9月` ,sum(`10月`*`数量`*`単価`) as `10月` ,sum(`11月`*`数量`*`単価`) as `11月` ,sum(`12月`*`数量`*`単価`) as `12月` ,sum(`1月`*`数量`*`単価`) as `1月` ,sum(`2月`*`数量`*`単価`) as `2月` ,sum(`3月`*`数量`*`単価`) as `3月` from tbl inner join pivot on 販売日 between mindate and maxdate group by 商品名;

ok-rjak
質問者

お礼

ピボットテーブル。Excelでは聞いたことありましたが、MySQLでも可能なのですね。 今後の参考にさせていただきます。 ありがとうございました。

  • t_ohta
  • ベストアンサー率38% (5085/13292)
回答No.1

select 商品名, EXTRACT(YEAR_MONTH FROM 販売日) as 販売月, sum(数量) as 合計数量, sum(数量 * 単価) as 合計金額 from テーブル group by 商品名, 販売月; あとは商品名と販売月でループさせながら表示する。

ok-rjak
質問者

お礼

ありがとうございます。 今回はNo.3の方の方法を採用させていただきました。 こちらの方法も、今後の参考にさせていただきます。

関連するQ&A

  • 1つのSQLで2段階の抽出を行いたい

    恐らくそれほど複雑なSQLではないと思いますが、中々SQLが作成できず困っています。 回答いただければ嬉しいです。 以下のテーブルがあったと仮定します。 テーブル名:  売上げ明細 カラム:  ・商品ID … 売上げ明細なので一意ではありません  ・単価 … 同じ商品IDでも、レコードによって単価は異なります  ・数量 … 1~5の整数のみとします 実際のデータは以下の通りです。 商品ID,単価,数量 1001,50,2 1001,60,5 1002,90,3 1003,60,5 1003,80,4 1003,90,1 1004,60,3 上記データを以下の通り抽出するには、どのようなSQLを組めばいいでしょうか? 1.まず各商品IDの中から単価が最大のレコードだけを取り出す 商品ID,単価,数量 1001,60,5 1002,90,3 1003,90,1 1004,60,3 2.次に数量でgroup by して、件数をカウントする 数量,件数 1,1 3,2 5,1 1つのSQL文で2の結果が得られれば、途中の抽出条件は特に問いません。 ちなみにMySQL5を使っています。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • エクセルで複数シートを一覧表にするには?

    教えてください。エクセルで複数シートを自動で別のシートに転記したいのですが、 やり方がわかりません。 各シートの空白部分を除いてデーターがある分だけを取り出して、金額に数式を入れて 合計金額を追加したいのですが・・・・・。 下記のような感じでできますか? 宜しくお願いいたします。    Sheet1     商品名  単価  数量        ****   000  000        ****    00   00   Sheet2     商品名  単価  数量        ****   000  000        ****    00   00   Sheet3     商品名  単価  数量        ****   000  000        ****    00   00 をSheet4に   シート名 商品名  単価  数量  金額   Sheet1  ****   000  000  0000(単価×数量)          ****    00   00  0000(単価×数量)                    合計金額  000   Sheet2 商品名  単価  数量  金額         ****   000  000  0000(単価×数量)         ****    00   00  0000(単価×数量)                   合計金額  000    Sheet3 商品名  単価  数量  金額         ****   000  000  0000(単価×数量)         ****    00   00  0000(単価×数量)                   合計金額  000

  • 単価×数量の関数

       A     B     C      D       E       F     G      H・・・ 1  商品1  詳細1   数量1    単価1   商品2    詳細2   数量2   単価2・・・詳細30  詳細30-(2) 2 リンゴ  2/1購入    1     100     梨     3/1購入    2     300    上記の様に、商品名、詳細、単価、数量が1行に記入されています。 これらの合計金額を計算する場合、通常でしたら =C2*D2+G2*H2・・・ という計算式と使用しますが、 品名が30を超える場合もあるので、上記の計算式では足していくのが非常に大変です。 何かほかに、簡単な関数はあるでしょうか? 宜しくお願いします。

  • phpとmysqlで抽出

    Mysqlに下記のようにデータがあります。 そこで、このデーター(日付)を 2013年1月1日(2件) 2013年1月2日(1件) 2013年1月3日(1件) 2013年1月5日(2件) のように抽出、集計したいです。 いろいろ考えましたが、ピンときませんorz どうすれば宜しいですか? お願いします。 Mysqlのデータ +--+---+ |ID |Dat| +--+--+ |1 | 20130101| +--+--+ |2 | 20130101| +--+--+ |3 | 20130102| +--+--+ |4 | 20130103| +--+--+ |5 | 20130105| +--+--+ |6 | 20130105| +--+--+

    • ベストアンサー
    • PHP
  • ACCESS2000のレポートでの合計の表示

    下記のレポートを作成しようと考えております。 [商品名][数量][単価][小計] ----------------------- あめ   2 20 40 ----------------------- せんべい 3 10 30 -----------------------        [合計]70 ところが作ると [商品名][数量][単価][小計] ----------------------- あめ   2 20 40 -----------------------        [合計]70 せんべい 3 10 30 -----------------------        [合計]70 となってしまいます。(合計が何回も出てくる) 「[合計]70」の部分は「商品名フッダー」 (後から表示に切り替えた)の部分に、記述 しています。 サンプロのNorthWind.mdbの納品書を参考ににして 作成したのですが、ダメでした。 どなたか、解決方法を教えていただけると ありがたいです。

  • エクセル★集計で数量合計を出したいのですぅが

    エクセルに詳しくないので、教えてほしいです。 下記のような表があります。データは500以上あります。 商品コード   商品名   数量    日付 12345    クッキー     10    13.10.11 12345    クッキー     25    13.12.12 12333    チョコ       11    13.10.22 12345    クッキー     50    13.10.11 12222    キャンディ    30    13.12.10 12333    チョコ       45    13.10.10 12333    チョコ       20    13.10.22 今までの表には、日付がなかったので、データ→集計で、簡単に、商品コード別の数量合計がだせていたのですが、今回新たに、日付が増えたましたので、商品コード別かつ日付別の、それぞれの数量合計を出したいのですが、データー→集計で出すことは可能でしょうか? 簡単な方法がありましたら、教えてほしいです。 よろしくお願いします。

  • MySQL+PHP 特定レコードの更新と作成

    MySQL+PHPの初心者です。 特定レコードの変更または新規作成のサンプルなどあればお教えいただけるでしょうか。 例えば特定商品の単価のレコードがあれば新しい単価に変更と そのレコードが無ければ新規にレコードを作成するようなケースになります。 VBAなどでは検索のSQL文からレコードセットを作成し レコードが無い場合は レコードセット名.addnewで必要なフィールドに 値をセットし レコードセット名.update 該当するレコードがあった場合は レコードセット名.edit で必要なフィールドに 値をセットし レコードセット名.updateなど簡単な処理なのですが MySQL+PHP の場合データの検索と新規レコードの単純な記述は ある程度はわかるのですが上記のようなケースは実際どのように 書かれているのかお教え願えると幸いです。 商品単価テーブルには商品コードと単価のフィールドになります。 よろしくお願いいたします。

    • ベストアンサー
    • MySQL
  • 条件に合うデータを別のブックに書き出したい

    お世話になります。 エクセル2003で、数量を入力した「行」だけを別のブックに書き出したいのですが、機能や関数を教えてください。 (表1)    A     B     C    D 1 商品名  単価  数量  合計 2  い    100   4    400 3  ろ    500   2    1,000 4  は    200 5  に    150 6  ほ    330 7  へ    230   5    1,150     ・     ・    ・    ・     ・     ・    ・    ・ 17  た    180   2    360 と、17行、4列の表があります。この「数量」が入力された行だけ、 (表2)   A    B    C   D 1 数量 単価 合計 商品名 2  4   100  400   い 3  2   500  1,000  ろ 4  5   230  1,150  へ 5  2   180  360   た (表2)のように書き出したいのです。 (表1)から抽出される行数は、必ず4行以下です。 (表1)に数量を入力すると、(表2)が自動的に変わるのが好ましいです。 マクロやVBAは苦手なのでエクセルの機能や関数で教えていただければ幸いに存じます。 情報が足りなければ補足します。 宜しくお願いします。

  • 単価・数量・金額 iphoneアプリ

    各商品の単価・数量を入力すれば、各商品の金額および全商品の合計金額が自動計算されるという、そういう機能に特化したiPhoneアプリはないでしょうか。無料でお願いします。

  • Excel データの抽出について

    年始のお忙しいところ失礼いたします。 Excelにおけるデータ抽出についてお尋ねいたします。 抽出元データは左から1番目のシートのA列から順に、日付、部門名、商品名、数量0、記号、数量1、記号、数量2、記号、数量3、記号、残り数量となっています。 残り数量の列には、『=数量0-数量1-数量2-数量3』 という数式が記述してあります。 今回は、左から3番目のシートに、商品名、数量0、残り数量の3列の条件式を入力する場所と条件式に合致するデータを表示する場所を作成して、条件式に合致するデータを抽出することを検討しています。 条件式 商品名列:商品名の中から1つの商品を抽出 数量0:数量0=40、数量0<=10など数量0の値が入力した任意の数量と=またはは、以下(<=)を抽出 残り数量:残り数量<>0、残り数量<=20など残り数量の値が0以外か、入力した任意の数量以下を抽出 条件式を書き換える(抽出条件を変更する)ことが多いため、書き換える(条件を変更する)たびに、表示されるデータが更新されるようにしたいです