2016-06-30 15 views
0

Ich habe eine Tabelle mit diesen Feldern (Modell, Datum, Preis, Menge) Ich brauche eine SQL (zu MySQL), die mir eine dynamische Tabelle mit dem Modellnamen, der Menge und dem Brutto gibt Verkauf (Preis * Menge), aber getrennt nach Monat (Datum). Beispielsweise.Pivot Daten in MySQL nach Monat

  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 

Danke !!

AKTUALISIERT:

Die Tabelle:

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

Geben Sie uns die eigentliche Definition der Tabelle, ist es wirklich in diesem Fall nicht helfen. –

+2

Besser noch, zeigen Sie uns Beispieldaten aus Ihrer Quellentabelle. –

+0

Dies kommt zu der Komplexität, wo ich sagen würde: Tun Sie dies auf der Anwendungsebene, anstatt in einer Abfrage. – Shadow

Antwort

0

Diese ziemlich schwierig ist, vielleicht gibt es einen besseren Weg, es zu tun, aber hier ist meine zwei Cent, beachten Sie, dass die gruppierten Spaltennamen in MySQL unmöglich ist, als Es gibt nur die Beziehung zwischen Spalten und Spaltennamen ist 1: 1.

Im Folgenden finden Sie einen Code, der Testdaten generiert und dann eine Prozedur erstellt, die auf dynamischem SQL basiert, um die Abfrage zu generieren, die erforderlich ist, um die Ergebnisse zurückzugeben, die ebenfalls dynamisch ausgeführt werden. Beachten Sie, dass der Code ohne Fehler ausgeführt werden sollte, DROP-Anweisungen jedoch kommentiert sind, um unerwünschte Schäden an Ihrer vorhandenen Struktur zu vermeiden. Die Prozedur RANDBETWEEN wird in der letzten gespeicherten Prozedur nicht benötigt, wird aber zum Generieren von Testdaten verwendet.

#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); 

Lassen Sie mich wissen, wenn Sie irgendwelche Fragen haben.

Grüße,

James

Verwandte Themen