Voy a añadir un poco más largo y más detallado explicación de los pasos a seguir para resolver este problema. Me disculpo si es demasiado largo.
Voy a empezar a cabo con la base que has dado y lo utilizan para definir un par de términos que voy a utilizar para el resto de este post. Esta será la tabla base de:
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Este será nuestro objetivo, los tabla dinámica bastante:
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Los valores en la columna de la history.hostid
se convertirán en y-valores en el tabla dinámica. Los valores en la columna history.itemname
se convertirán en x-values (por razones obvias).
Cuando tengo que resolver el problema de la creación de una tabla dinámica, I abordarlo utilizando un proceso de tres pasos (con un cuarto paso opcional):
- seleccionar las columnas de interés, es decir,y-valores y valores x
- extienden la tabla base con columnas adicionales - una para cada uno x-valor
- grupo y el agregado de la mesa extendida - un grupo para cada valor de y
- (opcional) prettify la tabla agregada
vamos a aplicar estas medidas para su problema y ver lo que obtenemos:
Paso 1: seleccione columnas de interés. En el resultado deseado, hostid
proporciona y-values y itemname
proporciona x-values .
Paso 2: extienda la tabla base con columnas adicionales. Por lo general, necesitamos una columna por valor x. Recordemos que nuestra columna valor de 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 hemos cambiado el número de filas - que acaba de agregar 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: agrupe y agregue la tabla extendida. Necesitamos group by hostid
, ya que proporciona los valores de y: (. Tenga en cuenta que ahora tenemos una fila por cada valor 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 |
+--------+------+------+------+
bien, estamos casi allí! Solo tenemos que deshacernos de esos feos NULL
s.
Paso 4: pretifique. Sólo vamos a reemplazar los valores nulos con ceros por lo que el conjunto de resultados es más agradable a la vista:
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 construido una tabla dinámica agradable, bonita utilizando MySQL.
Consideraciones al aplicar este procedimiento:
- que 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 ser 0
o ""
, dependiendo de su situación exacta
- qué función agregada utilizar al agrupar. Usé
sum
, pero también se usan a menudo count
y max
(max
se usa a menudo al construir "objetos" de una fila que se han distribuido en muchas filas)
- usando múltiples columnas para valores y.Esta solución no se limita a la utilización de una sola columna para los valores de y - sólo tiene que enchufar las columnas adicionales en la cláusula
group by
(y no se olvide de ellos select
)
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 x, esta solución es agradable. Para 100, no tan agradable. Hay algunas soluciones con procedimientos almacenados que generan una consulta, pero son feas y difíciles de corregir. Actualmente no sé de una buena manera de resolver este problema cuando la tabla pivote necesita tener muchas columnas.
@ Rob, ¿Puede por favor editar la pregunta para incluir la consulta exacta? – Johan