web-dev-qa-db-fra.com

Requête Mysql pour convertir dynamiquement des lignes en colonnes

MySQL peut-il convertir des colonnes en lignes, en ajoutant dynamiquement autant de colonnes que nécessaire pour les lignes. Je pense que ma question pourrait être liée aux tableaux croisés dynamiques, mais je ne suis pas sûr et je ne sais pas comment cadrer cette question autrement qu'en donnant l'exemple suivant.

Étant donné deux tableaux A et B, qui ressemblent à

Tableau A

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

J'aime écrire une requête qui ressemble à ceci:

Tableau des résultats

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

Fondamentalement, je veux transformer chaque ligne du tableau B en une colonne du tableau des résultats. S'il y avait une nouvelle entrée a été ajoutée à la table B pour id = 1, alors je veux que la table de résultat s'étende automatiquement d'une colonne pour accueillir ce point de données supplémentaire.

34
Dom

Vous pouvez utiliser GROUP BY et MAX pour simuler le pivot. MySQL prend également en charge l'instruction IF.

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

Si vous avez plusieurs valeurs de order, le SQL dynamique peut être plus approprié pour que vous n'ayez pas à modifier la requête:

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;

SORTIE DES DEUX DEMANDES:

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

Vous devez utiliser MAX et GROUP BY pour simuler un PIVOT:

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

Et voici le SQL Fiddle .

5
sgeddes