group by で重複行を、縦横に展開する方法について

このQ&Aのポイント
  • テーブル名「masta」には「hinmei」、「tani」、「hiduke」、「ryou」というフィールドがあります。このテーブルのデータを横に展開したい場合、SQLの「GROUP BY」句を使用して集計することができます。
  • 具体的には、「Hinmei」、「Tani」、「Hiduke」を「GROUP BY」し、集計関数「SUM」を使用して「ryou」を合計します。このようにして集計したデータをテーブルの横方向に展開することができます。
  • 以下のSQLを使用すると、指定した期間(200801から200812)のデータを「Hinmei」と「Tani」でグループ化し、「Hiduke」ごとに「ryou」を合計することができます。そして、合計したデータをテーブルの横方向に展開して表示することができます。 SELECT Hinmei, Tani, SUM(ryou) as ryou FROM masuta WHERE hiduke BETWEEN '200801' AND '200812' GROUP BY Hinmei, Tani
回答を見る
  • ベストアンサー

group by で重複行を、縦横に展開したい

下記のようなテーブルがあります。 テーブル名:masta フィールド:hinmei,tani,hiduke,ryou これを 品名 | 単位 |1月|2月|3月| A   |リットル|10|20|30| B   |グラム |12|13|14| のようにてんかいしたいのです。 現在SQLは SELECT Hinmei ,Tani ,Hiduke ,SUM(ryou) as ryou FROM masuta WHERE hiduke BETWEEN '200801' AND '200812' GROUP BY Hinmei ,Tani ,Hiduke このようにしてますが、横てんかいの方法が分かりません。 どのようなSQLをかけばいいのでしょうか?

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

  • ベストアンサー
回答No.1

例えば、こんな感じ。 SELECT Hinmei, Tani, SUBSTR(hiduke,1,4) as Nen, SUM(CASE SUBSTR(hiduke,5,2) WHEN '01' THEN ryou ELSE 0 END) as "1月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '02' THEN ryou ELSE 0 END) as "2月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '03' THEN ryou ELSE 0 END) as "3月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '04' THEN ryou ELSE 0 END) as "4月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '10' THEN ryou ELSE 0 END) as "10月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '11' THEN ryou ELSE 0 END) as "11月", SUM(CASE SUBSTR(hiduke,5,2) WHEN '12' THEN ryou ELSE 0 END) as "12月" FROM masta WHERE hiduke BETWEEN '200801' AND '200812' GROUP BY Hinmei,Tani,Nen

wagonahru
質問者

お礼

すばらしいです。 こんなに早く回答をもらえるとは思いませんでした。 ここに、書き込みするのも初めてなんです。 実際にSQLを打ち込んで、見事表ができました。 ありがとうございました。

関連するQ&A

  • group by句

    色々と試行錯誤してやっていますが、なかなか自分の 思うような結果が得られないためご質問させて下さい。 テーブルが全部で3つあります。 テーブルA id name 1 巨人 2   西武 テーブルB id name 1 小笠原 2 ラミレス 3 中島 4  片岡 テーブルC id テーブルAID テーブルBID 背番号 1 1 1 30 2 1 2 10 3 2 3 3 4 2 4 8 テーブルを結合し、テーブルCにある 背番号をテーブルAid,テーブルBidを元に sumしたいのですがうまくいきません。 以下がそのSQLになります。 (1)サブクエリーを使ったSQL この場合値が重複されて表示されてしまいます。 select a.name,b.name,c.name, (select sum(背番号) from tableC c where c.テーブルAId = a.id group by c.テーブルAid ), (select sum(背番号) from tableC c where c.テーブルBid = bid group by c.テーブルBid ) from tableC c inner join tableA a on a.id = c.テーブルAid inner join tableB b on b.id = c.テーブルBid (2) select a.name,b.name,c.name, (select sum(背番号) from tableC c where c.テーブルAId = a.id ), (select sum(背番号) from tableC c where c.テーブルBid = bid ) from tableC c inner join tableA a on a.id = c.テーブルAid inner join tableB b on b.id = c.テーブルBid group by c.テーブルAid 重複はされないのですが、group byが一つのみなので ちゃんとした出力がされません。    他にやり方があるのかもしれませんが、お分かりになる方が    いらっしゃいましたら、ご教授お願い致します。

  • SQLServerのPIVOT絡みの処理

    お世話になります。 従来はVB6のプログラム中で、従来ACCESSMDBからデータを取得していました。 これをDBを変更し、データ自体はOracle、接続先はSQLServer(2005)との仕組みに変更することとなりました。 (SQLServerのリンクサーバ機能にてOracleからデータを取得する) ここで、元のアクセスにて行っていたクロス集計を移行するため 次のようなSQL文(メイン部位以外は端折ってます)を書いたのですが、 「オペランドのデータ型 nvarchar は sum 演算子では無効です」 との警告が出てしまいます。 (”SUM(oraData.suuryou)” を、”Count(oraData.suuryou)”とした場合はデータ取得できました。) 原因、及び回避策についてお知恵を拝借できませんでしょうか? (PIVOT相当の処理をプログラム側で行うことで回避できますが、できればSQLで終えてしまいたいです) SELECT     pvt.moji    ,pvt.moji2    ,SUM([01]), SUM([02]), SUM([03]), SUM([04]), SUM([05]), SUM([06]), SUM([07]), SUM([08]), SUM([09]), SUM([10])     ,SUM([11]), SUM([12]), SUM([13]), SUM([14]), SUM([15]), SUM([16]), SUM([17]), SUM([18]), SUM([19]), SUM([20])     ,SUM([21]), SUM([22]), SUM([23]), SUM([24]), SUM([25]), SUM([26]), SUM([27]), SUM([28]), SUM([29]), SUM([30])     ,SUM([31])  From    openquery  (LinkServerName, '      SELECT        moji       ,moji2       ,hiduke       ,TO_CHAR(hiduke, ''dd'') AS dd       ,hiduke       ,suuryou       ,Sum(suuryou) AS suuryou      FROM        table      WHERE        hiduke BETWEEN TO_DATE(''2008/04/01'', ''YYYY/MM/DD'') AND TO_DATE(''2008/04/30'', ''YYYY/MM/DD'')       UNION      SELECT        moji       ,moji2       ,hiduke       ,TO_CHAR(hiduke, ''dd'') AS dd       ,hiduke       ,suuryou       ,Sum(suuryou) AS suuryou      FROM        table      WHERE        hiduke BETWEEN TO_DATE(''2008/04/01'', ''YYYY/MM/DD'') AND TO_DATE(''2008/04/30'', ''YYYY/MM/DD'')     ') AS oraData PIVOT     (         SUM(oraData.suuryou)         FOR oraData.dd IN           (              [01], [02], [03], [04], [05], [06], [07], [08], [09], [10]              ,[11], [12], [13], [14], [15], [16], [17], [18], [19], [20]              ,[21], [22], [23], [24], [25], [26], [27], [28], [29], [30]              ,[31]            )      ) AS pvt WHERE    moji = "xxx" OR moji2 = "yyy"

  • select文でGROUP BYの正しい使い方

    下記のselect文は問題ないでしょうか?テーブルには5つのフィールド(id,name,age,gender,office)が存在します。 select * from テーブル名 where age >= '40' GROUP BY gender 実際に試したところ、うまく動いているのですが、GROUP BY句で指定されたフィールド名はSELECT句のフィールド指定をすべて含んでいなくてはならないと書かれているのを見つけました。 上記のselect文は正しいのでしょうか。

    • ベストアンサー
    • PHP
  • SQL文について教えてください。

    お世話になります。 テーブルを3つ作りました ユーザーテーブル:USER_MS USE_NO USER_NAME 001   太郎 002   次郎 003   三郎 品名テーブル:HINMEI_MS HINMEI_NO HINMEI_NAME 001    りんご 002    みかん 003    イチゴ 嫌いなものテーブル:KIRAI_TR KIRAI_NO USER_NO HINMEI_NO 001001  001   001 002003  002   003 002001  002   001 ※KIRAI_NO=USER_NO.HINMEI_NO と連結してプライマリーキーにした ここで、次郎の嫌いなものを抽出するときには $USER_NO = '002'; $SQL ="SELECT * FROM KITAI_TR A,HINMEI_MS B WHERE A.USER_NO = '$USER_NO'; で抽出できるのですが、 次郎の嫌いでない002みかんだけを抽出するSQL文がわからず苦慮しています。 以前、オラクルでSQLを使ったことがあったのですが、その時はFROM句の後に(SELECT * FORM・・・・) Bなどと書くと通ったのですがMYSQLでは通りませんでした。 よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 五十音順

    テーブルのフィールドに、読み仮名が入っています。 あ行、か行など、五十音順に抽出する場合のSQL文ですが、 $sql = 'select * from テーブル名 where kana between "あ" and "お" order by kana'; 上記の文を $sql = 'select * from テーブル名 where kana between "$key[$i]" order by kana'; という具合に配列などに入れたいと考えておりますが。 そのようなことは可能なのでしょうか? それとも、もっと効率よく五十音順の検索ができるようにする方法が ありますでしょうか?

  • タイムスタンプ型を抽出条件に指定した場合のSQL

    タイムスタンプ型を抽出条件に指定した場合、どの様なSQL文を指定すれば良いでしょうか? 該当するレコードは確かに存在していますが、以下のSQL文では「空」になってしまいました。 【実行したSQL文】 SELECT フィールド FROM テーブル WHERE タムスタンプ型フィールド BETWEEN '2011-08-05 20:00:00' AND '2011-08-06 19:59:59' 何卒、ご教授頂ければと存じます。 宜しくお願いします。

    • ベストアンサー
    • MySQL
  • 一定以上の行があれば最大値を持つ行を削除するSQL

    MySQL5にて、あるテーブルの特定フィールドの数(つまりcount値)が一定値以上であれば、間引きのため別のフィールドの値で最大値をもつ行を削除するSQLを考案中です。 イメージとしては以下の通りですが、SQLとしては誤っており、また、冗長です。 DELETE FROM table WHERE id={$id} AND (SELECT COUNT(*) FROM table WHERE id={$id}) > 5 AND begin = (SELECT MAX(begin) FROM table WHERE id={$id}); よい知恵をお授けください。

    • ベストアンサー
    • MySQL
  • SQLの書き方を教えて!

    select name,SUM(kingak) from where date between 150221 and 150320 group by frjpc.trcd のようにSUMで集計を行うSQLを発行する時に,同時にkingak順にsortすることは可能なのでしょうか? select name,SUM(kingak) from where date between 150221 and 150320 group by frjpc.trcd order by SUM(kingak) としたいところですが,これではエラーになりますね。 SQLでは解決できないんでしょうか?

  • データベースのワイルドカードは%ではないの?

    アクセスのテーブルに あ い う があり、 SQL文で *********************************************** SELECT テーブル1.フィールド FROM テーブル1 WHERE (((テーブル1.フィールド) Like "%あ%")); *********************************************** としてもエラーにならないけど、「あ」が抽出されません。 *********************************************** SELECT テーブル1.フィールド FROM テーブル1 WHERE (((テーブル1.フィールド) Like "*あ*")); *********************************************** にすると、「あ」が抽出されます。 アクセスなどのデータベースのワイルドカードは%だと思っていたのですが違うのですか?

  • Access特有の決まりごと 日付表記法

    Accessのクエリで(1)SQLを書くと(2)に変換されました、Access特有の決まりごとがあるのでしょうか? (1) update テストテーブル set テストフィールド = 1 where 日付 between #2009/02/05# and #2009/04/30# (2) update テストテーブル set テストフィールド = 1 where 日付 between #2/5/2009# and #4/30/2009#; 月/日/年の表示は、あまり馴染みありません。