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
此外,我按 r
和 val
分组,然后按 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数据表或任何我们可以复制和粘贴的东西(代码)的图像。幸运的是,这只有几行数据,因此重新创建更容易,但如果他们看到照片,则没有多少人愿意提供帮助。
我有一个 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
此外,我按 r
和 val
分组,然后按 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数据表或任何我们可以复制和粘贴的东西(代码)的图像。幸运的是,这只有几行数据,因此重新创建更容易,但如果他们看到照片,则没有多少人愿意提供帮助。