Я збираюся додати дещо більш тривале та детальне пояснення кроків, які потрібно вжити для вирішення цієї проблеми. Прошу вибачення, якщо це занадто довго.
Почну з основи, яку ви надали, і використаю її, щоб визначити пару термінів, які я використовуватиму для решти цієї публікації. Це буде основна таблиця :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Це буде нашою метою, симпатичною зведеною таблицею :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Значення в history.hostid
стовпці стануть y-значеннями у зведеній таблиці. Значення в history.itemname
стовпці стануть x-значеннями (з очевидних причин).
Коли мені доведеться вирішити проблему створення зведеної таблиці, я вирішую її за допомогою триетапного процесу (з необов'язковим четвертим кроком):
- виберіть стовпці, що цікавлять, тобто y-значення та x-значення
- розгорніть базову таблицю додатковими стовпцями - по одному для кожного x-значення
- групуйте та агрегуйте розширену таблицю - по одній групі для кожного y-значення
- (необов’язково) оформити збірну таблицю
Давайте застосуємо ці кроки до вашої проблеми і подивимося, що ми отримаємо:
Крок 1: виберіть цікаві стовпці . У бажаному результаті hostid
надається значення y та itemname
надається значення x .
Крок 2: розгорніть базову таблицю додатковими стовпцями . Зазвичай нам потрібен один стовпець на значення x. Нагадаємо, що наш стовпець x-значення 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 |
+--------+----------+-----------+------+------+------+
Зауважте, що кількість рядків ми не змінили - ми просто додали додаткові стовпці. Також зверніть увагу на шаблон NULL
s - рядок з itemname = "A"
має ненулеве значення для нового стовпця A
, а значення null для інших нових стовпців.
Крок 3: згрупуйте та об’єднайте розширену таблицю . Нам потрібно group by hostid
, оскільки це забезпечує 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 |
+--------+------+------+------+
(Зверніть увагу, що зараз у нас є один рядок на y-значення.) Гаразд, ми майже там! Нам просто потрібно позбутися тих потворнихNULL
с.
Крок 4: підготуйте . Ми просто замінимо будь-які нульові значення нулями, щоб набір результатів було краще придивитися:
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 |
+--------+------+------+------+
І ми закінчили - ми створили гарну, досить вивірну таблицю за допомогою MySQL.
Примітки при застосуванні цієї процедури:
- яке значення використовувати в додаткових стовпцях. я використав
itemvalue
у цьому прикладі
- яке "нейтральне" значення використовувати в додаткових стовпцях. Я звик
NULL
, але це теж могло бути0
або ""
, залежно від вашої точної ситуації
- яку агрегатну функцію використовувати при групуванні. Я використовував
sum
, але count
іmax
також часто використовуються (max
часто використовується при створенні одного рядка «об'єкти» , які були поширені в багатьох рядах)
- використовуючи кілька стовпців для значень y. Це рішення не обмежується використанням одного стовпця для значень y - просто підключіть додаткові стовпці до
group by
пункту (і не забудьте про select
них)
Відомі обмеження:
- це рішення не дозволяє n стовпців у зведеній таблиці - кожен поворотний стовпець потрібно вручну додати під час розширення базової таблиці. Отже, для 5 або 10 x-значень це рішення добре. Для 100 не дуже приємно. Існує кілька рішень із збереженими процедурами, що генерують запит, але вони некрасиві і їх важко отримати правильно. На даний момент я не знаю, як вдало вирішити цю проблему, коли в зведеній таблиці потрібно мати багато стовпців.