Voy a añadir una explicación algo más larga y detallada de los pasos a seguir para solucionar este problema. Me disculpo si es demasiado largo.
Comenzaré con la base que me diste y la usaré para definir un par de términos que usaré en el resto de esta publicación. Esta será la tabla base :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Este será nuestro objetivo, la bonita tabla dinámica :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Valores en history.hostid
la columna se convertirá en valores y en la tabla dinámica. Valores en history.itemname
la columna se convertirá en valores x (por razones obvias).
Cuando tengo que resolver el problema de crear una tabla dinámica, lo afronto mediante un proceso de tres pasos (con un cuarto paso opcional):
- seleccione las columnas de interés, es decir, valores y y valores x
- amplíe la tabla base con columnas adicionales, una para cada valor x
- agrupar y agregar la tabla extendida:un grupo para cada valor de y
- (opcional) embellecer la tabla agregada
Apliquemos estos pasos a su problema y veamos qué obtenemos:
Paso 1:selecciona columnas de interés . En el resultado deseado, hostid
proporciona los valores y y itemname
proporciona los valores x .
Paso 2:amplía la tabla base con columnas adicionales . Por lo general, necesitamos una columna por valor de x. Recuerde que nuestra columna de valor x es 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 |
+--------+----------+-----------+------+------+------+
Tenga en cuenta que no cambiamos el número de filas, solo agregamos columnas adicionales. También tenga en cuenta el patrón de NULL
s -- una fila con itemname = "A"
tiene un valor no nulo para la nueva columna A
y valores nulos para las otras columnas nuevas.
Paso 3:agrupar y agregar la tabla extendida . Necesitamos group by hostid
, ya que proporciona los valores de 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 |
+--------+------+------+------+
(Tenga en cuenta que ahora tenemos una fila por valor y). Bien, ¡ya casi llegamos! Solo tenemos que deshacernos de esos feos NULL
s.
Paso 4:embellecer . Simplemente vamos a reemplazar cualquier valor nulo con ceros para que el conjunto de resultados sea más agradable de ver:
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 |
+--------+------+------+------+
Y hemos terminado:hemos creado una tabla dinámica agradable y bonita con MySQL.
Consideraciones al aplicar este procedimiento:
- qué valor usar en las columnas adicionales. Usé
itemvalue
en este ejemplo - qué valor "neutral" usar en las columnas adicionales. Usé
NULL
, pero también podría ser0
o""
, dependiendo de su situación exacta - qué función agregada utilizar al agrupar. Usé
sum
, perocount
ymax
también se utilizan a menudo (max
se usa a menudo cuando se construyen "objetos" de una fila que se han distribuido en muchas filas) - utilizando varias columnas para los valores de y. Esta solución no se limita a usar una sola columna para los valores de y, simplemente inserte las columnas adicionales en el
group by
cláusula (y no olvideselect
ellos)
Limitaciones conocidas:
- esta solución no permite n columnas en la tabla dinámica:cada columna dinámica debe agregarse manualmente al extender la tabla base. Entonces, para 5 o 10 valores de x, esta solución es buena. Por 100, no tan agradable. Hay algunas soluciones con procedimientos almacenados que generan una consulta, pero son desagradables y difíciles de corregir. Actualmente no conozco una buena manera de resolver este problema cuando la tabla dinámica necesita tener muchas columnas.