Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL - Zeilen zu Spalten

Ich werde eine etwas längere und detailliertere Erklärung der Schritte hinzufügen, die zur Lösung dieses Problems zu unternehmen sind. Ich entschuldige mich, wenn es zu lang ist.

Ich beginne mit der Basis, die Sie gegeben haben, und verwende sie, um ein paar Begriffe zu definieren, 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 |
+--------+----------+-----------+

Das wird unser Ziel sein, die hübsche Pivot-Tabelle :

select * from history_itemvalue_pivot;

+--------+------+------+------+
| hostid | A    | B    | C    |
+--------+------+------+------+
|      1 |   10 |    3 |    0 |
|      2 |    9 |    0 |   40 |
+--------+------+------+------+

Werte in history.hostid Spalte wird zu y-Werten in der Pivottabelle. Werte in history.itemname Spalte wird zu x-Werten (aus offensichtlichen Gründen).

Wenn ich das Problem der Erstellung einer Pivot-Tabelle lösen muss, gehe ich es mit einem dreistufigen Prozess an (mit einem optionalen vierten Schritt):

  1. wählen Sie die gewünschten Spalten aus, d. h. y-Werte und x-Werte
  2. Erweitern Sie die Basistabelle mit zusätzlichen Spalten – eine für jeden x-Wert
  3. gruppieren und aggregieren Sie die erweiterte Tabelle – eine Gruppe für jeden y-Wert
  4. (optional) die aggregierte Tabelle verschönern

Lassen Sie uns diese Schritte auf Ihr Problem anwenden und sehen, was wir bekommen:

Schritt 1:Interessante Spalten auswählen . Im gewünschten Ergebnis hostid liefert die y-Werte und itemname liefert die x-Werte .

Schritt 2:Erweitern Sie die Basistabelle mit zusätzlichen Spalten . Normalerweise benötigen wir eine Spalte pro x-Wert. Denken Sie daran, dass unsere x-Wert-Spalte itemname ist :

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, sondern nur zusätzliche Spalten hinzugefügt haben. Beachten Sie auch das Muster von NULL s -- eine Zeile mit itemname = "A" hat einen Nicht-Null-Wert für die 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 loswerden s.

Schritt 4:Verschönern . Wir werden einfach alle Nullwerte durch Nullen ersetzen, damit die Ergebnismenge besser anzusehen ist:

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 hübsche Pivot-Tabelle erstellt.

Überlegungen zur Anwendung dieses Verfahrens:

  • welcher Wert in den zusätzlichen Spalten verwendet werden soll. Ich habe itemvalue verwendet in diesem Beispiel
  • welcher "neutrale" Wert in den zusätzlichen Spalten verwendet werden soll. Ich habe NULL verwendet , könnte aber auch 0 sein oder "" , abhängig von Ihrer genauen Situation
  • welche Aggregatfunktion beim Gruppieren verwendet werden soll. Ich habe sum verwendet , aber count und max werden auch oft verwendet (max wird oft verwendet, wenn einzeilige "Objekte" erstellt werden, die über viele Zeilen verteilt wurden)
  • Mehrere Spalten für y-Werte verwenden. Diese Lösung ist nicht darauf beschränkt, eine einzige Spalte für die y-Werte zu verwenden – stecken Sie einfach die zusätzlichen Spalten in group by -Klausel (und vergessen Sie nicht, select sie)

Bekannte Einschränkungen:

  • diese Lösung erlaubt keine n Spalten in der Pivot-Tabelle – jede Pivot-Spalte muss manuell hinzugefügt werden, wenn die Basistabelle erweitert wird. 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 richtig zu machen. Ich kenne derzeit keine gute Möglichkeit, dieses Problem zu lösen, wenn die Pivot-Tabelle viele Spalten haben muss.