これは多分そこにそれを行うには良い方法だが、ここに私の2セントだ、としてMySQLには不可能であるグループ化されたカラム名ことに注意して、かなりトリッキーです列と列の名前の間には1:1の関係しかありません。
以下はいくつかのコードですが、テストデータを生成し、ダイナミックSQLを使用して必要な結果を返すのに必要なクエリを生成するプロシージャを構築し、動的に実行されます。コードはエラーなしで実行する必要がありますが、DROPステートメントは既存の構造に対する望ましくない損傷を防ぐためにコメント化されています。 RANDBETWEENプロシージャは、最終的なストアド・プロシージャでは不要ですが、テスト・データの生成に使用されます。
#DROP TABLE IF EXISTS sales;
CREATE TABLE `sales` (
`model` varchar(64) DEFAULT NULL,
`price` int DEFAULT NULL,
`quantity` int(2) DEFAULT NULL,
`date` datetime
);
SET @VMinModel := 1;
SET @VMaxModel := 5;
SET @VMinPrice := 10;
SET @VMaxPrice := 100;
SET @VMinQuantity := 1;
SET @VMaxQuantity := 10;
SET @VMinTime := UNIX_TIMESTAMP('2016-01-01');
SET @VMaxTime := UNIX_TIMESTAMP('2016-12-31');
#DROP FUNCTION RANDBETWEEN;
DELIMITER $
CREATE FUNCTION RANDBETWEEN(VMin INTEGER UNSIGNED, VMax INTEGER UNSIGNED) RETURNS INTEGER UNSIGNED
DETERMINISTIC
BEGIN
RETURN ROUND(RAND() * (VMax - VMin) + VMin);
END$
DELIMITER ;
INSERT INTO `sales` SELECT RANDBETWEEN(@VMinModel, @VMaxModel), RANDBETWEEN(@VMinPrice, @VMaxPrice), RANDBETWEEN(@VMinQuantity, @VMaxQuantity), FROM_UNIXTIME(RANDBETWEEN(@VMinTime, @VMaxTime)) FROM information_schema.COLUMNS LIMIT 1000;
SET @VXDimension := 'model';
SET @VYDimension := 'DATE_FORMAT(date, ''%Y-%m'')';
SET @VMeasures := 'quantity, quantity * price';
SET @VTable := 'sales';
#DROP PROCEDURE IF EXISTS singleDimensionMeltAndCast;
DELIMITER $
CREATE PROCEDURE singleDimensionMeltAndCast (VXDimension CHAR(255), VYDimension CHAR(255), VMeasures CHAR(255), VTable CHAR(255))
BEGIN
SET SESSION group_concat_max_len = 65536;
DROP TEMPORARY TABLE IF EXISTS YDimensionValues;
SET @VCreateYDimensionValueTable := CONCAT('CREATE TEMPORARY TABLE YDimensionValues SELECT DISTINCT ', VYDimension, ' AS YDim1 FROM ', VTable, ' ORDER BY ', VYDimension, ' ASC;');
PREPARE stmt FROM @VCreateYDimensionValueTable;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TEMPORARY TABLE IF EXISTS Measures;
CREATE TEMPORARY TABLE Measures (measure CHAR(255));
SET @VCreateMeasuresTable := CONCAT('INSERT INTO Measures VALUES(''', REPLACE(VMeasures, ', ', '''), ('''), ''')');
PREPARE stmt FROM @VCreateMeasuresTable;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @VYDimensionSQLFieldsComponent = (SELECT GROUP_CONCAT('SUM(IF(', VYDimension, ' = ''', YDim1, ''', ', measure, ', 0)) `[', YDim1, ' x ', measure, ']`' SEPARATOR ', ') FROM YDimensionValues, Measures WHERE TRUE);
SET @VYDimensionSQLGroupComponent = (SELECT GROUP_CONCAT('IF(', VYDimension, ' = ''', YDim1, ''', ', measure, ', 0)' SEPARATOR ', ') FROM YDimensionValues, Measures WHERE TRUE);
SET @VFinalQuery := CONCAT('SELECT ', VXDimension, ', ', @VYDimensionSQLFieldsComponent, ' FROM ', VTable, ' GROUP BY ', @VYDimensionSQLGroupComponent, ' ORDER BY ', VXDimension, ';');
PREPARE stmt FROM @VFinalQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$
DELIMITER ;
CALL singleDimensionMeltAndCast(@VXDimension, @VYDimension, @VMeasures, @VTable);
ご不明な点がありましたら教えてください。
よろしく、
ジェームズ
は私達にあなたのテーブルの実際の定義を与える、本当にこのインスタンスで助けになるだろう。 –
さらに、ソーステーブルのサンプルデータを表示してください。 –
これは、私が言うところの複雑さを増しています。これは、クエリではなくアプリケーションレベルで行います。 – Shadow