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

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

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

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

SQL

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

Q&A

解決済

3回答

3958閲覧

MYSQL でクロス集計の逆のようなことをしたい

umikaze21

総合スコア13

MySQL

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

SQL

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

0グッド

0クリップ

投稿2016/07/24 01:56

編集2016/07/24 02:22

###前提・実現したいこと
Mysql 5.5.36 にて テーブルデータから出力結果のようなテーブルを得たいのですが
どのようなSQL文を書けばよろしいでしょうか?

テーブルデータ
key a b c

あ 11 12 13
い 21 22 23
う 31 32 33

出力結果
row1 row2 val

a あ 11
a い 21
a う 31
b あ 12
b い 22
b う 32
c あ 13
c い 23
c う 33

###試したこと
SELECT CONCAT( "a" ) AS row1, key as row2, a AS val FROM テーブルデータ
union
SELECT CONCAT( "b" ) AS row1, key as row2, b AS val FROM テーブルデータ
union
SELECT CONCAT( "c" ) AS row1, key as row2, c AS val FROM テーブルデータ

上記のようなSQL文で一応できますが、実際にはカラム数が多いのでしんどいです。
カラム数が増えてもSQL分は変わらないようにできないものでしょうか?

select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
where COLUMN_NAME != "Key" and TABLE_NAME = 'テーブルデータ' order by TABLE_NAME

のようにカラム名を取得する分を絡めればよさそうですがその先は検討が付きません。

助言などいただければ幸いです。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2016/07/24 02:00

row1 row2 val の値、間違ってませんか?
umikaze21

2016/07/24 02:21

テーブル2の出力結果のほうが間違っていました。 また、SQL文のテーブル名も本文と微妙に違っていたので訂正しました。 ご指摘ありがとうございました。
guest

回答3

0

これはa,b,cをデータとして渡せば簡単なロジックです

SQL

1create table tbl(`key` varchar(10),A int,B int,C int); 2insert into tbl values('あ',11,12,13),('い',21,22,23),('う',31,32,33); 3create table tmp(row1 varchar(10)); 4insert into tmp values('a'),('b'),('c');

表示

SQL

1select row1,`key` as row2,case 2when row1='a' then A 3when row1='b' then B 4when row1='c' then C 5end as value 6from tbl,tmp 7order by row1,value;

tmpテーブルはテンポラリテーブルとして作っても構いません

追記

ピボットテーブル的なアプローチをすると書き方がすっきりするかも

SQL

1create table pivot(row1 varchar(10),pA int null,pB int null,pC int null); 2insert into pivot values('a',1,null,null),('b',null,1,null),('c',null,null,1);

表示

SQL

1select row1,`key` as row2,coalesce(A*pA,B*pB,C*pC) as value 2from tbl,pivot;

投稿2016/07/25 00:42

編集2016/07/25 01:15
yambejp

総合スコア114761

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

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

umikaze21

2016/07/25 13:04

回答ありがとうございました。 最初のテーブルとそのテーブルを管理するためのテーブルとSQL文の3つの同期をとるのが少し不安に思えました。しかし、そのアルゴリズムというか構造はすごく勉強になりました。また、Mysqlの勉強を始めて間もないのでcoalesce自体初めて知ったのでもうちょっと基礎から勉強していきたいと思います。。。
guest

0

ベストアンサー

SQL一本に収めるなら下記のような感じですかねぇ・・・。

SQL

1SELECT 2 B.COLUMN_NAME 3 , T.key 4 , CASE B.COLUMN_NAME 5 WHEN 'a' THEN T.a 6 WHEN 'b' THEN T.b 7 WHEN 'c' THEN T.c 8 ELSE NULL 9 END AS VAL 10FROM 11 テーブルデータ T 12 CROSS JOIN ( 13 SELECT 14 COLUMN_NAME 15 FROM 16 INFORMATION_SCHEMA.COLUMNS 17 WHERE 18 COLUMN_NAME != "key" 19 AND TABLE_NAME = 'テーブルデータ' 20 ) B 21ORDER BY 22 B.COLUMN_NAME 23 , T.key

ただCROSS JOINを行っている都合上パフォーマンス面に不安はあるのと、
カラム追加があると結局微々たる修正は必要です。

上記が許容できない場合はshi_ueさんの回答のようにストアド化するのがベストかと思います。

ストアドの内部で動的SQL化するとカラム追加があっても、
ストアド側の変更は不要となりますしね^^

投稿2016/07/24 14:58

編集2016/07/24 15:10
Panzer_vor

総合スコア1636

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

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

umikaze21

2016/07/25 13:16

回答ありがとうございます。 今回は私のような初心者が趣味でやっていることもあり、あまりレコード数は大きくならない見込みなので、性能より理解のしやすさ重視でこちらをベストアンサーにさせていただきたいと思います。大変たすかりました!
guest

0

自分の学習がてら、ストアドプロシージャーを書いてみました。
カーソルというものを使っています。

SQL

1DELIMITER // 2CREATE PROCEDURE demo() 3BEGIN 4 DECLARE done INT DEFAULT FALSE; 5 DECLARE field VARCHAR(20); 6 DECLARE cur CURSOR FOR SELECT COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME != 'key' and TABLE_NAME = 'テーブル名' order by COLUMN_NAME; 7 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 8 9 OPEN cur; 10 SET @STMT = ''; 11 read_loop: LOOP 12 FETCH cur INTO field; 13 IF done THEN 14 LEAVE read_loop; 15 END IF; 16 IF @STMT != '' THEN 17 SET @STMT = CONCAT(@STMT,' UNION '); 18 END IF; 19 SET @STMT = CONCAT(@STMT, 'SELECT "',field,'" AS row1, `key` AS row2,',field,' AS val FROM テーブル名'); 20 END LOOP; 21 CLOSE cur; 22 23 PREPARE stmt FROM @STMT; 24 EXECUTE stmt; 25 26END 27// 28DELIMITER ; 29```要するにはフィールドの一覧を取得し、UNIONクエリSQLを生成→取得する、ってだけです。 30`CALL demo`とやると取得できます。 31 32もっといいやり方があるかもしれませんが・・・ 33 34追記 35--- 36フィールド名直書きでいいなら、 37```SQL 38SELECT 39 F.row1, 40 T.`key` AS row2, 41 CASE F.row1 42 WHEN 'a' THEN T.A 43 WHEN 'b' THEN T.B 44 WHEN 'c' THEN T.C 45 END AS val 46FROM tbl AS T, 47 (SELECT COLUMN_NAME AS row1 48 FROM INFORMATION_SCHEMA.COLUMNS 49 WHERE COLUMN_NAME != 'key' AND TABLE_NAME = 'tbl') AS F 50ORDER BY row1,row2; 51```でいいね。

投稿2016/07/24 11:33

編集2016/07/25 13:34
shi_ue

総合スコア4437

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

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

shi_ue

2016/07/25 13:22

なんだ、 > カラム数が増えてもSQL分は変わらないようにできないものでしょうか? って書いてあるのにBAがカラム名直書きとは・・・
umikaze21

2016/07/25 13:25

回答ありがとうございます。 しかしながら、ストアドプロシージャーは私にはハードルが高すぎました(泣 しかし、このようなアプローチもあるということで、とても貴重なとっかかりを頂いたとは思います。これから少しづつでも勉強していきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問