我尝试搜索帖子,但仅找到SQL Server / Access的解决方案。我需要MySQL(5.X)中的解决方案。
我有一个表(称为历史记录),其中包含3列:hostid,itemname,itemvalue。
如果我选择(select * from history
),它将返回
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
+--------+----------+-----------+
| 1 | B | 3 |
+--------+----------+-----------+
| 2 | A | 9 |
+--------+----------+-----------+
| 2 | c | 40 |
+--------+----------+-----------+
我如何查询数据库以返回类似
+--------+------+-----+-----+
| hostid | A | B | C |
+--------+------+-----+-----+
| 1 | 10 | 3 | 0 |
+--------+------+-----+-----+
| 2 | 9 | 0 | 40 |
+--------+------+-----+-----+
最佳答案
我将对解决此问题所采取的步骤添加一个更长一些且更详细的解释。如果时间太长,我深表歉意。
我将从您给出的基础开始,并使用它来定义几个术语,这些术语将在本文的其余部分中使用。这将是基本表:
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
的模式-带有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,不是很好。存储过程有一些解决方案可以生成查询,但是它们很丑陋,很难解决。当数据透视表需要有很多列时,我目前不知道解决此问题的好方法。
关于mysql - MySQL-行到列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46843609/