MySQLでクロス集計
SQLでクロス集計する際、該当がない項目も水平軸にしないと
漏れがでてしまうと考えたことはないでしょうか?
該当がある項目を2つ、縦に並べるのは標準で備わっているので
何の造作もないことでしょう。
例えば、
SELECT 縦カラム,横カラム名,COUNT(*) 件数
FROM スキーマ名.テーブル名
GROUP BY 縦カラム,横カラム名;
で完成です。
しかし、横カラムのデータを水平方向に並べた、所謂クロス集計
をしたいと思った途端、横カラムの異なるデータの個数が動的(
言い換えれば不定)なので、SQLを書くことができない。
ありうる全ての種類が受容限度以下なら、該当データが無いこと
を承知でSQLを書くこともできるでしょう。
実は、何個のカラムを用意すればいいのかは、SQLで直ぐわかって
しまうことです。
例えば, SELECT DISTINCT 横カラム名 FROM ....;
で済んでしまいます。
そこで、この結果を人間が見てSQLを書き下す代わりに、
SQL自分自身でSQLで作成する事はできないのかと言うことを
見ましょう。
そうすると、
SELECT 縦カラム,
式1 AS 横カラム1,
式2 AS 横カラム2,
...
式n AS 横カラムn
FROM ... GROUP BY 縦カラム;
生成できそうな気がしませんか?
SQLで生成しななくてもいい部分は、固定文字列にして
おけば完成のハズですね。
ではここで具体例を示します。
DROP TEMPORARY TABLE IF EXISTS temp.wrk ;
CREATE TEMPORARY TABLE temp.wrk
SELECT DISTINCT TbL.横カラム名
FROM スキーマ名.テーブル名 TbL
LEFT JOIN ~~~~~~
WHERE ~~~~~~ AND
~~~~~~ AND
. . . . . . . . .
~~~~~~ ;
DROP TEMPORARY TABLE IF EXISTS temp.tmp ;
CREATE TEMPORARY TABLE temp.tmp (cmd VARCHAR(128)) ;
INSERT INTO temp.tmp VALUES
("SELECT 式 AS 縦カラム) ;
INSERT INTO temp.tmp
(SELECT CONCAT(" SUM(", 縦カラム, ") AS ", 縦カラム, ", ") FROM temp.wrk);
INSERT INTO temp.tmp VALUES
(" SUM(合計) 合計 "),
(" FROM ("),
(" SELECT TbL.横カラム名,TbL.縦カラム名,") ;
INSERT INTO temp.tmp
(SELECT CONCAT(" SUM(IF(AcT.横カラム名='", 横カラム, "' , 1 ,0)) AS ", 横カラム, ",") FROM temp.wrk);
INSERT INTO temp.tmp VALUES
(" SUM(1) 合計"),
(" FROM スキーマ名.テーブル名 Tbl"),
(" LEFT JOIN ~~~~~~"),
(" WHERE ~~~~~~ AND"),
(" ~~~~~~ AND"),
. . . . . .. . . . . .
(" ~~~~~~"),
(" GROUP BY 1,2,"),
(" ) tmp"),
(" GROUP BY 1 WITH ROLLUP;"),;
SELECT * FROM temp.tmp
;