Je vais ajouter une explication un peu plus longue et plus détaillée des étapes à suivre pour résoudre ce problème. Je m'excuse si c'est trop long.
Je vais commencer par la base que vous avez donnée et l'utiliser pour définir quelques termes que j'utiliserai pour le reste de cet article. Ce sera la table de base :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Ce sera notre objectif, le joli tableau croisé dynamique :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Les valeurs de la history.hostid
colonne deviendront des valeurs y dans le tableau croisé dynamique. Les valeurs de la history.itemname
colonne deviendront des valeurs x (pour des raisons évidentes).
Lorsque je dois résoudre le problème de la création d'un tableau croisé dynamique, je l'aborde en utilisant un processus en trois étapes (avec une quatrième étape facultative):
- sélectionnez les colonnes d'intérêt, c'est -à- dire les valeurs y et les valeurs x
- étendre la table de base avec des colonnes supplémentaires - une pour chaque valeur x
- grouper et agréger la table étendue - un groupe pour chaque valeur y
- (facultatif) joliment la table agrégée
Appliquons ces étapes à votre problème et voyons ce que nous obtenons:
Étape 1: sélectionnez les colonnes d'intérêt . Dans le résultat souhaité, hostid
fournit les valeurs y et itemname
fournit les valeurs de x .
Étape 2: prolongez la table de base avec des colonnes supplémentaires . Nous avons généralement besoin d'une colonne par valeur x. Rappelez-vous que notre colonne de valeur x est itemname
:
create view history_extended as (
select
history.*,
case when itemname = "A" then itemvalue end as A,
case when itemname = "B" then itemvalue end as B,
case when itemname = "C" then itemvalue end as C
from history
);
select * from history_extended;
+--------+----------+-----------+------+------+------+
| hostid | itemname | itemvalue | A | B | C |
+--------+----------+-----------+------+------+------+
| 1 | A | 10 | 10 | NULL | NULL |
| 1 | B | 3 | NULL | 3 | NULL |
| 2 | A | 9 | 9 | NULL | NULL |
| 2 | C | 40 | NULL | NULL | 40 |
+--------+----------+-----------+------+------+------+
Notez que nous n'avons pas changé le nombre de lignes - nous avons simplement ajouté des colonnes supplémentaires. Notez également le modèle de NULL
s - une ligne avec itemname = "A"
a une valeur non nulle pour la nouvelle colonne A
et des valeurs nulles pour les autres nouvelles colonnes.
Étape 3: regroupez et agrégez la table étendue . Nous devons group by hostid
, car il fournit les valeurs y:
create view history_itemvalue_pivot as (
select
hostid,
sum(A) as A,
sum(B) as B,
sum(C) as C
from history_extended
group by hostid
);
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | NULL |
| 2 | 9 | NULL | 40 |
+--------+------+------+------+
(Notez que nous avons maintenant une ligne par valeur y.) D'accord, nous y sommes presque! Nous devons juste nous débarrasser de ces horribles NULL
s.
Étape 4: joliment . Nous allons simplement remplacer toutes les valeurs nulles par des zéros afin que le jeu de résultats soit plus agréable à regarder:
create view history_itemvalue_pivot_pretty as (
select
hostid,
coalesce(A, 0) as A,
coalesce(B, 0) as B,
coalesce(C, 0) as C
from history_itemvalue_pivot
);
select * from history_itemvalue_pivot_pretty;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Et nous avons terminé - nous avons construit un joli tableau croisé dynamique en utilisant MySQL.
Considérations lors de l'application de cette procédure:
- quelle valeur utiliser dans les colonnes supplémentaires. J'ai utilisé
itemvalue
dans cet exemple
- quelle valeur «neutre» utiliser dans les colonnes supplémentaires. J'ai utilisé
NULL
, mais cela pourrait aussi être 0
ou ""
, selon votre situation exacte
- quelle fonction d'agrégat utiliser lors du regroupement. J'ai utilisé
sum
, mais count
et max
sont aussi souvent utilisés ( max
est souvent utilisé lors de la création d '"objets" à une ligne qui avaient été répartis sur plusieurs lignes)
- en utilisant plusieurs colonnes pour les valeurs y. Cette solution ne se limite pas à utiliser une seule colonne pour les valeurs y - branchez simplement les colonnes supplémentaires dans la
group by
clause (et ne les oubliez select
pas)
Limitations connues:
- cette solution n'autorise pas n colonnes dans le tableau croisé dynamique - chaque colonne pivot doit être ajoutée manuellement lors de l'extension de la table de base. Donc pour 5 ou 10 valeurs x, cette solution est sympa. Pour 100, pas si gentil. Il existe certaines solutions avec des procédures stockées générant une requête, mais elles sont laides et difficiles à obtenir. Je ne connais actuellement pas de bon moyen de résoudre ce problème lorsque le tableau croisé dynamique a besoin de beaucoup de colonnes.