MySql 枢轴未知数量的列标题

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)

FaN*_*_FN 5

首先要做的是将列变成行。方法简单;只需要使用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)

此外,我已按 分组rval然后按 排序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:下次,请不要发布数据表的图像或我们可以复制和粘贴的任何内容(代码)。幸运的是,它只有几个数据行,因此更容易重新创建,但如果他们看到照片,则没有多少人愿意提供帮助。