MySQL GROUP BY WITH ROLLUP,如何强制汇总行中的空白值?

问题描述 投票:0回答:1

这与这个问题几乎是同一个问题,但我仍然无法使其与我的数据一起工作。

我有两个由 Fee_name 连接的表。 我正在选择费用,执行组计数,进行计算并获得汇总总数。 我最初的 SQL 可以得到我想要的数值结果。

但是,汇总行显示与其上方行相同的费用 (17.70),这是没有意义的,因为汇总总额不对应于任何费用。 我试图在汇总行的费用列中获取一个空字符串。 (类似于其他 SO 帖子)

任何人都可以告诉我哪里出错了,并帮助我为我的表格提供正确的代码吗?

我已经展示了三种进一步尝试获得正确的 SQL 和结果,但这些尝试仍然没有给我想要的结果,包括来自 here 的以下建议 (请注意,这些进一步的尝试故意显示原始费用列,并添加一个额外的列,并尝试在该列中获取空字符串)

这是我的两张桌子

bmc_fee -(只有 3 行)

|fee_name | fee   | 
|Adult    | 23.90 | 
|Student  | 19.75 | 
|U18      | 17.70 | 

bmctypes -(大约有 600 行)

|fee_name |
|Adult    |
|Adult    |
|Adult    |
|Student  |
|Adult    |
|U18      |
|Student  |
etc...

我最初的SQL

SELECT
   IF(GROUPING(bmctypes.fee_name), 'xTotal', bmctypes.fee_name) AS fee_name,
   COUNT(*) AS num,
   bmc_fee.fee, 
   bmc_fee.fee * COUNT(*)  AS expense
FROM  bmctypes 
JOIN bmc_fee 
ON bmc_fee.fee_name  = bmctypes.fee_name
GROUP BY bmctypes.fee_name WITH ROLLUP;

预期结果(xTotal 行的费用列中为空白)

|fee_name | num | fee   | expense  |
|Adult    | 560 | 23.90 | 13384.00 |
|Student  |   3 | 19.75 |    59.25 |
|U18      |  10 | 17.70 |   177.00 |
|xTotal   | 573 |       | 10142.10 |

我的初步结果(xTotal 汇总行的费用列中为 17.70)

|fee_name | num | fee   | expense  |
|Adult    | 560 | 23.90 | 13384.00 |
|Student  |   3 | 19.75 |    59.25 |
|U18      |  10 | 17.70 |   177.00 |
|xTotal   | 573 | 17.70 | 10142.10 |

尝试 2,使用 IF() 并添加额外的列以帮助调试

SELECT
   IF(GROUPING(bmctypes.fee_name), 'xTotal', bmctypes.fee_name) AS fee_name,
   COUNT(*) AS num,
   bmc_fee.fee as fee_1, 
   IF(fee_name ='xTotal','',bmc_fee.fee) AS fee_2,
   bmc_fee.fee * COUNT(*)  AS expense
FROM  bmctypes 
JOIN bmc_fee 
ON bmc_fee.fee_name  = bmctypes.fee_name
GROUP BY bmctypes.fee_name WITH ROLLUP;

使用 IF() 进行尝试 2 的结果

|fee_name | num | fee_1 | fee_2 | expense  |
|Adult    | 560 | 23.90 | (NULL)| 13384.00 |
|Student  |   3 | 19.75 | (NULL |    59.25 |
|U18      |  10 | 17.70 | (NULL |   177.00 |
|xTotal   | 573 | 17.70 | (NULL)| 10142.10 |

尝试 3 使用第二个 GROUPING() 并添加额外的列以帮助调试

SELECT
   IF(GROUPING(bmctypes.fee_name), 'xTotal', bmctypes.fee_name) AS fee_name,
   COUNT(*) AS num,
   fee as fee_1,  
   IF(GROUPING(fee_name), '', bmc_fee.fee) AS fee_2,
   bmc_fee.fee * COUNT(*)  AS expense
FROM  bmctypes 
JOIN bmc_fee 
ON bmc_fee.fee_name  = bmctypes.fee_name
GROUP BY bmctypes.fee_name WITH ROLLUP;

尝试3的结果

|fee_name | num | fee_1 | fee_2 | expense  |
|Adult    | 560 | 23.90 | (NULL)| 13384.00 |
|Student  |   3 | 19.75 | (NULL |    59.25 |
|U18      |  10 | 17.70 | (NULL |   177.00 |
|xTotal   | 573 | 17.70 |       | 10142.10 |

尝试4,遵循SO链接中的建议

SELECT
   COALESCE(bmctypes.fee_name,'xTotal') AS fee_name,
   COUNT(*) AS num,
   fee as fee_1,  
  (CASE WHEN bmctypes.fee_nameIS NULL THEN NULL ELSE fee END) AS fee_col_2,
   bmc_fee.fee * COUNT(*)  AS expense
FROM  bmctypes 
JOIN bmc_fee 
ON bmc_fee.fee_name  = bmctypes.fee_name
GROUP BY bmctypes.fee_name WITH ROLLUP;

COALESCE 和 CASE 的结果

|fee_name | num | fee_1 | fee_2 | expense  |
|Adult    | 560 | 23.90 | (NULL)| 13384.00 |
|Student  |   3 | 19.75 | (NULL |    59.25 |
|U18      |  10 | 17.70 | (NULL |   177.00 |
|xTotal   | 573 | 17.70 | (NULL)| 10142.10 |
mysql rollup
1个回答
0
投票

解决方案如下:

SELECT
   COALESCE(bmc_fee.fee_name, 'xTotal') AS fee_name,
   COUNT(*) AS num,
   IF(GROUPING(bmc_fee.fee_name), NULL, MAX(bmc_fee.fee)) as fee,
   SUM(bmc_fee.fee) AS expense
FROM bmc_fee
JOIN bmctypes ON bmc_fee.fee_name  = bmctypes.fee_name
GROUP BY bmc_fee.fee_name WITH ROLLUP;

给定样本数据的输出:

+----------+-----+-------+---------+
| fee_name | num | fee   | expense |
+----------+-----+-------+---------+
| Adult    |   4 | 23.90 |   95.60 |
| Student  |   2 | 19.75 |   39.50 |
| U18      |   1 | 17.70 |   17.70 |
| xTotal   |   7 |  NULL |  152.80 |
+----------+-----+-------+---------+

Dbfiddle:https://www.db-fiddle.com/f/cu5YYscLmhUb6ZYnPUt2Zz/0

在您的示例所需的输出中,最后一行的费用小于每行费用的总和。我猜这是因为它计算的是 17.70 费用的总计数,而不是实际总和。我上面显示的查询解决方案汇总了实际费用。

© www.soinside.com 2019 - 2024. All rights reserved.