VBS*_*arr 0 mysql sql pivot dynamic-pivot
我有一个 MySql 查询,我想动态地旋转该查询,将公司名称作为列标题,将公司财务字段作为行标题。
目前我有这个:
SELECT Company, TotalRevenue, Overhead, TotalJobCosts, GrossProfit
FROM comp_financials
Run Code Online (Sandbox Code Playgroud)
这给了我这个:
| 公司 | 总收入 | 高架 | 总工作成本 | 毛利 |
|---|---|---|---|---|
| 芝加哥最好的建筑 | 2098001 | 363750 | 1424420 | 673581 |
| 琼斯建筑公司 | 4509458 | 1067008 | 2876568 | 1632890 |
我希望得到这样的东西:
| 芝加哥最好的建筑 | 琼斯建筑公司 | |
|---|---|---|
| 总收入 | 2098001 | 4509458 |
| 高架 | 363750 | 1067008 |
| 总工作成本 | 1424420 | 2876568 |
| 毛利 | 673581 | 1632890 |
拥有未知数量的公司及其价值(但通常少于 20 家)。
到目前为止,我已经将公司名称动态显示为列标题,但无法了解如何显示行值(行标题不是必需的)。
SET @@group_concat_max_len = 32000;
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE WHEN Company = ''',
Company,
''' THEN Company ELSE NULL END) AS ',
CONCAT('`', Company, '`')
)) INTO @sql
FROM comp_financials;
SET @sql = CONCAT('SELECT ', @sql, '
FROM comp_financials');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Run Code Online (Sandbox Code Playgroud)
首先要做的是将列变成行。方法简单;只需要使用UNION ALL. 像这样的东西:
SELECT 1 as r,company, "TotalRevenue" val, TotalRevenue totals FROM comp_financials UNION ALL
SELECT 2, company, "Overhead", Overhead FROM comp_financials UNION ALL
SELECT 3, company, "TotalJobCosts", TotalJobCosts FROM comp_financials UNION ALL
SELECT 4, company, "GrossProfit", GrossProfit FROM comp_financials
Run Code Online (Sandbox Code Playgroud)
我添加了编号 ( .. as r) 以供以后在ORDER BY. val值对应于我从中检索数据的列名称。该查询将返回如下数据:
| r | 公司 | 瓦尔 | 总计 |
|---|---|---|---|
| 1 | 琼斯建筑公司 | 总收入 | 4509458 |
| 1 | 芝加哥最好的建筑 | 总收入 | 2098001 |
| 2 | 琼斯建筑公司 | 高架 | 1067008 |
| 2 | 芝加哥最好的建筑 | 高架 | 363750 |
| 3 | 琼斯建筑公司 | 总工作成本 | 2876568 |
| 3 | 芝加哥最好的建筑 | 总工作成本 | 1424420 |
| 4 | 琼斯建筑公司 | 毛利 | 1632890 |
| 4 | 芝加哥最好的建筑 | 毛利 | 673581 |
上面的查询是我对您正在进行的原始查询的派生查询。所以最终结果如下所示:
SELECT r,val,
MAX(CASE WHEN company="Jones construction" THEN totals END) AS "Jones construction",
MAX(CASE WHEN company="Chicago's Best Construction" THEN totals END) AS "Chicago's Best Construction"
FROM
(SELECT 1 as r,company, "TotalRevenue" val, TotalRevenue totals FROM comp_financials UNION ALL
SELECT 2, company, "Overhead", Overhead FROM comp_financials UNION ALL
SELECT 3, company, "TotalJobCosts", TotalJobCosts FROM comp_financials UNION ALL
SELECT 4, company, "GrossProfit", GrossProfit FROM comp_financials) B
GROUP BY r,val
ORDER BY r ASC
Run Code Online (Sandbox Code Playgroud)
此外,我已按 分组r,val然后按 排序r。该查询返回如下数据:
| r | 瓦尔 | 琼斯建筑 | 芝加哥最好的建筑 |
|---|---|---|---|
| 1 | 总收入 | 4509458 | 2098001 |
| 2 | 高架 | 1067008 | 363750 |
| 3 | 总工作成本 | 2876568 | 1424420 |
| 4 | 毛利 | 1632890 | 673581 |
将其添加到您准备好的声明中:
SET @@group_concat_max_len = 32000;
SET @sql = NULL;
SELECT GROUP_CONCAT(DISTINCT
CONCAT('MAX(CASE WHEN Company = "',
Company,
'" THEN totals ELSE NULL END) AS ',
CONCAT('"', Company, '"')
)) INTO @sql
FROM comp_financials;
SET @sql = CONCAT('SELECT r,val, ', @sql, '
FROM
(SELECT 1 as r,company, "TotalRevenue" val, TotalRevenue totals FROM comp_financials UNION ALL
SELECT 2, company, "Overhead", Overhead FROM comp_financials UNION ALL
SELECT 3, company, "TotalJobCosts", TotalJobCosts FROM comp_financials UNION ALL
SELECT 4, company, "GrossProfit", GrossProfit FROM comp_financials) B
GROUP BY r,val
ORDER BY r ASC');
select @sql;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Run Code Online (Sandbox Code Playgroud)
这是一个演示小提琴:https://dbfiddle.uk/ ?rdbms=mysql_5.7&fiddle=678de8991e21ccd90d2195d3d5eca0a7
P/S:下次,请不要发布数据表的图像或我们可以复制和粘贴的任何内容(代码)。幸运的是,它只有几个数据行,因此更容易重新创建,但如果他们看到照片,则没有多少人愿意提供帮助。