MySql 未知列数的主元 headers

MySql pivot for unknown number of column headers

我有一个 MySql 查询,我想动态转换它,公司名称作为列 headers,公司财务字段作为行 headers。

目前我有这个:

SELECT Company, TotalRevenue, Overhead, TotalJobCosts, GrossProfit 
FROM comp_financials

这给了我这个:

Company TotalRevenue Overhead TotalJobCosts GrossProfit
Chicago's Best Construction 2098001 363750 1424420 673581
Jones Construction 4509458 1067008 2876568 1632890

我希望得到这样的东西:

Chicago's Best Construction Jones Construction
TotalRevenue 2098001 4509458
Overhead 363750 1067008
TotalJobCosts 1424420 2876568
GrossProfit 673581 1632890

公司数量及其价值未知(但通常少于 20 家)。

到目前为止,我已经能够动态地将公司名称显示为列 headers,但无法了解如何显示行值(不需要行 headers)。

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;

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

我添加了编号 (.. as r) 供以后在 ORDER BY 中使用。 val 值对应于我从中检索数据的列名。此查询将 return 如下数据:

r company val totals
1 Jones Construction TotalRevenue 4509458
1 Chicago's Best Construction TotalRevenue 2098001
2 Jones Construction Overhead 1067008
2 Chicago's Best Construction Overhead 363750
3 Jones Construction TotalJobCosts 2876568
3 Chicago's Best Construction TotalJobCosts 1424420
4 Jones Construction GrossProfit 1632890
4 Chicago's Best Construction GrossProfit 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

此外,我按 rval 分组,然后按 r 排序。此查询 returns 数据如下:

r val Jones construction Chicago's Best Construction
1 TotalRevenue 4509458 2098001
2 Overhead 1067008 363750
3 TotalJobCosts 2876568 1424420
4 GrossProfit 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;

这是一个演示 fiddle:https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=678de8991e21ccd90d2195d3d5eca0a7

P/S: 下次请不要post数据表或任何我们可以复制和粘贴的东西(代码)的图像。幸运的是,这只有几行数据,因此重新创建更容易,但如果他们看到照片,则没有多少人愿意提供帮助。