【问题标题】:MySql pivot for unknown number of column headersMySql 透视未知数量的列标题
【发布时间】:2021-02-22 02:01:57
【问题描述】:

我有一个 MySql 查询,我想动态调整它,公司名称作为列标题,公司财务字段作为行标题。

目前我有这个:

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 家)。

到目前为止,我已经将公司名称动态显示为列标题,但不知道如何显示行值(不需要行标题)。

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;

【问题讨论】:

  • 预期输出中Jones Construction 的值与第一个查询结果不同。
  • @FaNo_FN - 这是固定的

标签: mysql sql pivot dynamic-pivot


【解决方案1】:

首先要做的是将列转换为行。方法简单;只需要使用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 值对应于我从中检索数据的列名。此查询将返回如下数据:

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 排序。此查询返回如下数据:

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;

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

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

【讨论】:

  • 是的,这可以解决问题。我用实际的表格替换了表格图像 - 很好的提醒。与其他 SQL 风格相比,MySql 让您在 Pivot 上跳了这么多圈。
  • 在最新的 MySQL 版本(尤其是 v 8 及更高版本)上可能有更简单的方法,但我对这些版本的了解有限。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
相关资源
最近更新 更多