Ich werde eine etwas längere und detailliertere Erläuterung der Schritte zur Lösung dieses Problems hinzufügen. Ich entschuldige mich, wenn es zu lang ist.
Ich beginne mit der Basis, die Sie angegeben haben, und definiere damit einige Begriffe, die ich für den Rest dieses Beitrags verwenden werde. Dies wird die Basistabelle sein :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Dies wird unser Ziel sein, der hübsche Pivot-Tisch :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Die Werte in der history.hostid
Spalte werden zu y-Werten in der Pivot-Tabelle. Die Werte in der history.itemname
Spalte werden (aus offensichtlichen Gründen) zu x-Werten .
Wenn ich das Problem der Erstellung einer Pivot-Tabelle lösen muss, gehe ich es in drei Schritten an (mit einem optionalen vierten Schritt):
- Wählen Sie die gewünschten Spalten aus, dh y-Werte und x-Werte
- Erweitern Sie die Basistabelle um zusätzliche Spalten - eine für jeden x-Wert
- Gruppieren und aggregieren Sie die erweiterte Tabelle - eine Gruppe für jeden y-Wert
- (optional) Verschönern Sie die aggregierte Tabelle
Lassen Sie uns diese Schritte auf Ihr Problem anwenden und sehen, was wir bekommen:
Schritt 1: Wählen Sie die gewünschten Spalten aus . Liefert im gewünschten Ergebnis hostid
die y-Werte und itemname
liefert die x-Werte .
Schritt 2: Erweitern Sie die Basistabelle um zusätzliche Spalten . Wir benötigen normalerweise eine Spalte pro x-Wert. Denken Sie daran, dass unsere x-Wert-Spalte lautet 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 |
+--------+----------+-----------+------+------+------+
Beachten Sie, dass wir die Anzahl der Zeilen nicht geändert haben - wir haben nur zusätzliche Spalten hinzugefügt. Beachten Sie auch das Muster von NULL
s - eine Zeile mit itemname = "A"
hat einen Wert ungleich Null für eine neue Spalte A
und Nullwerte für die anderen neuen Spalten.
Schritt 3: Gruppieren und aggregieren Sie die erweiterte Tabelle . Wir müssen group by hostid
, da es die y-Werte liefert:
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 |
+--------+------+------+------+
(Beachten Sie, dass wir jetzt eine Zeile pro y-Wert haben.) Okay, wir sind fast da! Wir müssen nur diese hässlichen NULL
s loswerden .
Schritt 4: verschönern . Wir werden nur alle Nullwerte durch Nullen ersetzen, damit die Ergebnismenge besser aussieht:
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 |
+--------+------+------+------+
Und wir sind fertig - wir haben mit MySQL eine schöne, hübsche Pivot-Tabelle erstellt.
Überlegungen bei der Anwendung dieses Verfahrens:
- Welchen Wert soll in den zusätzlichen Spalten verwendet werden? Ich habe
itemvalue
in diesem Beispiel verwendet
- Welchen "neutralen" Wert soll in den zusätzlichen Spalten verwendet werden? Ich habe verwendet
NULL
, aber es könnte auch sein, 0
oder ""
, abhängig von Ihrer genauen Situation
- Welche Aggregatfunktion soll beim Gruppieren verwendet werden? Ich habe verwendet
sum
, aber count
und werde max
auch oft verwendet ( max
wird oft verwendet, wenn einzeilige "Objekte" erstellt werden, die über viele Zeilen verteilt waren)
- Verwenden mehrerer Spalten für y-Werte. Diese Lösung beschränkt sich nicht nur auf die Verwendung einer einzelnen Spalte für die y-Werte. Fügen Sie einfach die zusätzlichen Spalten in die
group by
Klausel ein (und vergessen Sie select
sie nicht).
Bekannte Einschränkungen:
- Diese Lösung erlaubt keine n Spalten in der Pivot-Tabelle. Jede Pivot-Spalte muss beim Erweitern der Basistabelle manuell hinzugefügt werden. Für 5 oder 10 x-Werte ist diese Lösung also gut. Für 100 nicht so schön. Es gibt einige Lösungen mit gespeicherten Prozeduren, die eine Abfrage generieren, aber sie sind hässlich und schwer zu finden. Ich kenne derzeit keinen guten Weg, um dieses Problem zu lösen, wenn die Pivot-Tabelle viele Spalten haben muss.