2013-02-12 33 views
30

MySQL può convertire colonne in righe, aggiungendo dinamicamente tutte le colonne necessarie per le righe. Penso che la mia domanda potrebbe essere correlata a tabelle pivot ma non sono sicuro e non so come inquadrare questa domanda se non dando il seguente esempio.Query Mysql per convertire dinamicamente le righe in colonne

Dato a due tabelle A e B, che assomigliano

Tabella A

+--+-----+----+ 
|id|order|data| 
+--+-----+----+ 
|1 |1 |P | 
+--+-----+----+ 
|2 |2 |Q | 
+--+-----+----+ 
|2 |1 |R | 
+--+-----+----+ 
|1 |2 |S | 
+--+-----+----+ 

mi piace scrivere una query che è simile al seguente:

Tabella Risultato

+--+-----+-----+ 
|id|data1|data2| 
+--+-----+-----+ 
|1 |P |S | 
+--+-----+-----+ 
|2 |R |Q | 
+--+-----+-----+ 

Fondamentalmente voglio trasformare ogni riga nella tabella B in una colonna nella tabella dei risultati. Se è stata aggiunta una nuova voce alla tabella B per id = 1, desidero che la tabella dei risultati si estenda automaticamente di una colonna per contenere questo punto dati aggiuntivo.

risposta

50

È possibile utilizzare GROUP BY e MAX per simulare il pivot. MySQL supporta anche la dichiarazione IF.

SELECT ID, 
     MAX(IF(`order` = 1, data, NULL)) data1, 
     MAX(IF(`order` = 2, data, NULL)) data2 
FROM TableA 
GROUP BY ID 

Se si dispone di più valori di order, SQL dinamico può essere più appropriato in modo che non sarà necessario modificare la query:

SET @sql = NULL; 
SELECT 
    GROUP_CONCAT(DISTINCT 
    CONCAT(
     'MAX(IF(`order` = ', `order`, ',data,NULL)) AS data', `order`) 
) INTO @sql 
FROM TableName; 

SET @sql = CONCAT('SELECT ID, ', @sql, ' 
        FROM TableName 
        GROUP BY ID'); 

PREPARE stmt FROM @sql; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 

USCITA DI entrambe le query:

╔════╦═══════╦═══════╗ 
║ ID ║ DATA1 ║ DATA2 ║ 
╠════╬═══════╬═══════╣ 
║ 1 ║ P  ║ S  ║ 
║ 2 ║ R  ║ Q  ║ 
╚════╩═══════╩═══════╝ 
+0

Fantastico, il secondo esempio è esattamente quello che ho chiesto. Sfortunatamente per me c'è un sacco di nuove sintassi SQL per capirci. – Dom

+0

quello con il prefisso '@' è chiamato variabili utente. e qui, http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html, per l'apprendimento di 'PreparedStatements'. –

+0

La soluzione sopra descritta funziona bene ma il mio scenario è che invece di applicare pivot su una colonna sulla base di un'altra ho anche altre colonne su cui voglio applicare il pivot sulla base di un'altra colonna. È come se applicassi due perni separati su due colonne di un tavolo e unendovi risultato. Qualsiasi aiuto – Moon

5

È necessario utilizzare MAX e GROUP BY per simulare un perno:

SELECT Id, 
    MAX(CASE WHEN Order = 1 THEN data END) data1, 
    MAX(CASE WHEN Order = 2 THEN data END) data2 
FROM TableA 
GROUP BY Id 

E qui è il SQL Fiddle.

+0

Questo non funziona in quanto è limitato a due colonne e impossibile gestire in modo dinamico l'aggiunta di colonne aggiuntive all'aumentare del numero o delle righe.Grazie per aver provato – Dom

+0

@Dom - non preoccuparti - SQL dinamico è la soluzione migliore se non conosci il numero massimo di ordini. Se fosse 10, allora aggiungi solo 10 istruzioni MAX :) - Sono contento di poter aiutare comunque. – sgeddes

+0

Downvoter, cura di spiegare? – sgeddes

Problemi correlati