2016-06-30 13 views
0

私はこのフィールド(モデル、日付、価格、数量)を持つテーブルを持っています 私にモデル名、数量、売上高(価格*数量)ですが、月(日付)で区切られています。例えば。MySQLのピボットデータを月単位で

  April   |   May   |  June 
Model |quantity| Gross Sales| quantity|Gross Sales| quantity | Gross Sales 
    1  6   50   4  40   5   45 
    2  10   30   3  9   5   15 

ありがとう!!

更新日:

テーブル:

CREATE TABLE `sales` (
     `model` varchar DEFAULT NULL, 
     `price` int DEFAULT NULL, 
     `quantity` int(2) DEFAULT NULL, 
     `date` timestamp 
    ) 
+1

は私達にあなたのテーブルの実際の定義を与える、本当にこのインスタンスで助けになるだろう。 –

+2

さらに、ソーステーブルのサンプルデータを表示してください。 –

+0

これは、私が言うところの複雑さを増しています。これは、クエリではなくアプリケーションレベルで行います。 – Shadow

答えて

0

これは多分そこにそれを行うには良い方法だが、ここに私の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); 

ご不明な点がありましたら教えてください。

よろしく、

ジェームズ

関連する問題