重塑表格以将行转换为列
我尝试搜索帖子,但只找到了 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 |
I tried to search posts, but I only found solutions for SQL Server/Access. I need a solution in MySQL (5.X).
I have a table (called history) with 3 columns: hostid, itemname, itemvalue.
If I do a select (select * from history
), it will return
hostid | itemname | itemvalue |
---|---|---|
1 | A | 10 |
1 | B | 3 |
2 | A | 9 |
2 | C | 40 |
How do I query the database to return something like
hostid | A | B | C |
---|---|---|---|
1 | 10 | 3 | 0 |
2 | 9 | 0 | 40 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
您可以使用几个
LEFT JOIN
。 请使用此代码You can use a couple of
LEFT JOIN
s. Kindly use this code如果您有许多需要旋转的项目,另一个选项特别有用,那就是让 mysql 为您构建查询:
FIDDLE
添加了一些额外的值以查看其工作情况
GROUP_CONCAT
的默认值为 1000,因此如果您有一个非常大的查询,请在运行测试之前更改此参数:
Another option,especially useful if you have many items you need to pivot is to let mysql build the query for you:
FIDDLE
Added some extra values to see it working
GROUP_CONCAT
has a default value of 1000 so if you have a really big query change this parameter before running itTest:
我将添加更长、更详细的说明来说明解决此问题所需的步骤。 如果太长,我深表歉意。
我将从您给出的基础开始,并用它来定义几个术语,我将在本文的其余部分使用这些术语。 这将是基表:
这将是我们的目标,漂亮的数据透视表:
history.hostid
列中的值将变为数据透视表中的 >y 值。history.itemname
列中的值将变为 x-values(出于显而易见的原因)。当我必须解决创建数据透视表的问题时,我使用三步过程(带有可选的第四步)来解决它:
让我们将这些步骤应用于您的问题,看看会得到什么:
第 1 步:选择感兴趣的列。 在所需的结果中,
hostid
提供y 值,itemname
提供x 值。第 2 步:使用额外的列扩展基表。 我们通常需要每个 x 值一列。 回想一下,我们的 x 值列是
itemname
:请注意,我们没有更改行数 - 我们只是添加了额外的列。 另请注意
NULL
的模式 - 具有itemname = "A"
的行的新列A
具有非空值,并且其他新列的空值。第3步:对扩展表进行分组和聚合。 我们需要
按主机 ID 进行分组
,因为它提供了 y 值:(请注意,我们现在每个 y 值一行。) 好的,我们就快到了! 我们只需要摆脱那些丑陋的
NULL
。第四步:美化。 我们将用零替换任何空值,以便结果集看起来更好:
我们就完成了——我们已经使用 MySQL 构建了一个漂亮的数据透视表。
应用此过程时的注意事项:
itemvalue
NULL
,但也可以是0
或""
,具体取决于您的具体情况,sum
,但是count
和max
也经常使用(max
经常在构建单行时使用) 使用多列group by
子句(并且不要忘记select
他们)已知的限制:
I'm going to add a somewhat longer and more detailed explanation of the steps to take to solve this problem. I apologize if it's too long.
I'll start out with the base you've given and use it to define a couple of terms that I'll use for the rest of this post. This will be the base table:
This will be our goal, the pretty pivot table:
Values in the
history.hostid
column will become y-values in the pivot table. Values in thehistory.itemname
column will become x-values (for obvious reasons).When I have to solve the problem of creating a pivot table, I tackle it using a three-step process (with an optional fourth step):
Let's apply these steps to your problem and see what we get:
Step 1: select columns of interest. In the desired result,
hostid
provides the y-values anditemname
provides the x-values.Step 2: extend the base table with extra columns. We typically need one column per x-value. Recall that our x-value column is
itemname
:Note that we didn't change the number of rows -- we just added extra columns. Also note the pattern of
NULL
s -- a row withitemname = "A"
has a non-null value for new columnA
, and null values for the other new columns.Step 3: group and aggregate the extended table. We need to
group by hostid
, since it provides the y-values:(Note that we now have one row per y-value.) Okay, we're almost there! We just need to get rid of those ugly
NULL
s.Step 4: prettify. We're just going to replace any null values with zeroes so the result set is nicer to look at:
And we're done -- we've built a nice, pretty pivot table using MySQL.
Considerations when applying this procedure:
itemvalue
in this exampleNULL
, but it could also be0
or""
, depending on your exact situationsum
, butcount
andmax
are also often used (max
is often used when building one-row "objects" that had been spread across many rows)group by
clause (and don't forget toselect
them)Known limitations:
利用 Matt Fenwick 帮助我解决问题的想法(非常感谢),让我们将其减少到只有一个查询:
Taking advantage of Matt Fenwick's idea that helped me to solve the problem (a lot of thanks), let's reduce it to only one query:
我从子查询中编辑 Agung Sagita 的答案来加入。
我不确定这两种方式有多大区别,仅供参考。
I edit Agung Sagita's answer from subquery to join.
I'm not sure about how much difference between this 2 way, but just for another reference.
使用子查询,
但如果子查询结果超过一行,就会出现问题,在子查询中使用进一步的聚合函数
use subquery
but it will be a problem if sub query resulting more than a row, use further aggregate function in the subquery
我的解决方案:
它在提交的案例中产生预期结果。
My solution :
It produces the expected results in the submitted case.
如果您可以使用 MariaDB 有一个非常非常简单的解决方案。
自 MariaDB-10.02 起,添加了一个名为 CONNECT< 的新存储引擎/a> 可以帮助我们将另一个查询或表的结果转换为数据透视表,就像您想要的那样:
您可以查看文档。
首先安装连接存储引擎。
现在我们表的数据透视表列是
itemname
并且每个项目的数据位于itemvalue
列中,因此我们可以使用此查询获得结果数据透视表:现在我们可以从
pivot_table
中选择我们想要的内容:更多详细信息在这里
If you could use MariaDB there is a very very easy solution.
Since MariaDB-10.02 there has been added a new storage engine called CONNECT that can help us to convert the results of another query or table into a pivot table, just like what you want:
You can have a look at the docs.
First of all install the connect storage engine.
Now the pivot column of our table is
itemname
and the data for each item is located initemvalue
column, so we can have the result pivot table using this query:Now we can select what we want from the
pivot_table
:More details here
我将其放入
Group By hostId
中,然后它将仅显示带有值的第一行,喜欢:
I make that into
Group By hostId
then it will show only first row with values,like:
我找到了一种方法,可以使用简单的查询使我的报告将行转换为几乎动态的列。 您可以在此处在线查看并测试它。
查询的列数是固定的,但值是动态的并且基于行的值。 您可以构建它因此,我使用一个查询来构建表头,并使用另一个查询来查看值:
您也可以对其进行总结:
RexTester:
http://rextester. com/ZSWKS28923
作为一个真实的使用示例,下面的报告以列形式显示了船只/公共汽车的出发到达时间和可视时间表。 您将看到最后一列未使用的附加列,而不会混淆可视化:
** 票务系统在线售票和赠品
I figure out one way to make my reports converting rows to columns almost dynamic using simple querys. You can see and test it online here.
The number of columns of query is fixed but the values are dynamic and based on values of rows. You can build it So, I use one query to build the table header and another one to see the values:
You can summarize it, too:
Results of RexTester:
http://rextester.com/ZSWKS28923
For one real example of use, this report bellow show in columns the hours of departures arrivals of boat/bus with a visual schedule. You will see one additional column not used at the last col without confuse the visualization:
** ticketing system to of sell ticket online and presential
这不是您正在寻找的确切答案,但这是我的项目所需的解决方案,希望这对某人有帮助。 这将列出 1 到 n 行项目,以逗号分隔。 Group_Concat 在 MySQL 中使这成为可能。
该墓地有两个通用名称,因此这些名称列在由单个 id 连接的不同行中,但有两个名称 id,查询会生成类似以下内容的内容
CemeteryID Cemetery_Name 纬度
1 阿普尔顿,萨尔弗斯普林斯 35.4276242832293
This isn't the exact answer you are looking for but it was a solution that i needed on my project and hope this helps someone. This will list 1 to n row items separated by commas. Group_Concat makes this possible in MySQL.
This cemetery has two common names so the names are listed in different rows connected by a single id but two name ids and the query produces something like this
CemeteryID Cemetery_Name Latitude
1 Appleton,Sulpher Springs 35.4276242832293
我很抱歉这么说,也许我没有完全解决你的问题,但 PostgreSQL 比 MySQL 早 10 年,并且比 MySQL 更加先进,并且有很多方法可以轻松实现这一点。 安装 PostgreSQL 并执行此查询
,然后瞧! 这里有大量文档: PostgreSQL: Documentation: 9.1: tablefunc 或此
查询再次瞧! PostgreSQL:文档:9.0:hstore
I'm sorry to say this and maybe I'm not solving your problem exactly but PostgreSQL is 10 years older than MySQL and is extremely advanced compared to MySQL and there's many ways to achieve this easily. Install PostgreSQL and execute this query
then voila! And here's extensive documentation: PostgreSQL: Documentation: 9.1: tablefunc or this query
then again voila! PostgreSQL: Documentation: 9.0: hstore