如何修改SUM CASE查询实现多日期score求和及同名字段累加?
问题描述
现有代码:
$scoreboard->selectRaw("SUM(CASE WHEN tgl IN ($dateFormat) THEN score ELSE 0 END) AS '$day'");
这段代码中,tgl字段会匹配$dateFormat(格式如'2022-12-01', '2023-01-01', '2023-02-01')中的值,匹配成功则累加score字段。但当前逻辑仅做OR判断,无法实现指定多个日期的score总和统计。
需解决两个问题:
- 如何改写该查询,实现对指定多个日期的score求和?
- 若两个查询使用相同的
AS $day(例如AS Day1),第二个查询的数据是否会累加到第一个中?
示例数据
| Name | tgl | score |
|---|---|---|
| A | 2022-12-01 | 100 |
| A | 2022-12-01 | 200 |
| A | 2022-12-01 | 300 |
| A | 2022-12-02 | 400 |
| A | 2022-01-01 | 100 |
| A | 2022-01-01 | 100 |
| A | 2022-01-03 | 200 |
| A | 2022-02-01 | 100 |
| A | 2022-02-01 | 200 |
| A | 2022-02-02 | 300 |
期望输出
| Name | Day 1 | Day 2 | Day 3 |
|---|---|---|---|
| A | 600 (sum of 2022-12-01) | 400 (sum of 2022-12-02) | 0 (无对应日期数据) |
| A | 100 (sum of 2022-01-01) | 0 (无对应日期数据) | 200 (sum of 2022-01-03) |
| A | 300 (sum of 2022-02-01) | 300 (sum of 2022-02-02) | 0 (无对应日期数据) |
解答
1. 改写查询实现多日期score求和
核心是要明确分组维度,并为每个目标日期单独编写统计逻辑,同时补充GROUP BY子句来得到分组后的结果:
场景1:按单个日期分别统计(对应期望输出的Day1/Day2/Day3)
如果需要对每个指定日期单独求和,要为每个日期写独立的SUM(CASE...),再按Name和日期所属的月份分组:
// 构建每个日期的统计字段 $selectFields = [ "SUM(CASE WHEN tgl = '2022-12-01' THEN score ELSE 0 END) AS 'Day 1'", "SUM(CASE WHEN tgl = '2022-12-02' THEN score ELSE 0 END) AS 'Day 2'", "SUM(CASE WHEN tgl = '2022-12-03' THEN score ELSE 0 END) AS 'Day 3'" ]; // 执行查询,按Name和月份分组 $scoreboard->select('Name') ->selectRaw(implode(', ', $selectFields)) ->groupBy('Name', DB::raw('DATE_FORMAT(tgl, "%Y-%m")'));
场景2:对一组日期整体求和
如果需要把多个日期的score合并到一个字段统计,原逻辑本身是可行的,但必须补充GROUP BY才能得到分组后的总和:
$dateList = "'2022-12-01', '2022-12-02'"; $scoreboard->select('Name') ->selectRaw("SUM(CASE WHEN tgl IN ($dateList) THEN score ELSE 0 END) AS 'DecTotal'") ->groupBy('Name');
2. 相同AS别名的查询是否会累加
不会。分两种情况:
- 同一
select语句中重复使用相同别名:数据库会直接报错,因为字段名不允许重复。 - 两次独立调用
selectRaw设置相同别名:后一次的字段会覆盖前一次的,最终结果只保留最后一次的计算值,不会累加。
如果需要实现累加,需在同一个SUM函数中合并条件,或通过子查询、CTE先分别统计再相加。
内容的提问来源于stack exchange,提问作者Retaker
相关产品推荐
相关产品推荐

