求助:基于Oracle SQL实现按档位聚合折扣的查询
解决Oracle SQL聚合折扣计算问题
根据你的需求,核心是区分全局适用折扣(Default和Bonus)和档位专属折扣(Extra)——前者需要加到所有购买档位的折扣中,后者只对应特定的Stretch/FromUnit档位。下面是两种清晰可行的实现方案:
方法一:用CTE拆分计算(逻辑直观易维护)
这种方式把全局折扣和档位折扣分开计算,再合并结果,可读性很强:
WITH global_base_discount AS ( -- 先算出全局通用的Default+Bonus折扣总和 SELECT SUM(Discount) AS total_base FROM your_table WHERE DiscType IN ('Default', 'Bonus') ), tier_extra_discounts AS ( -- 按Stretch和FromUnit分组,计算每个档位的Extra折扣 SELECT Stretch, FromUnit, SUM(Discount) AS total_extra FROM your_table WHERE DiscType = 'Extra' GROUP BY Stretch, FromUnit ) -- 把全局基础折扣和对应档位的Extra折扣相加 SELECT ted.Stretch, ted.FromUnit, ted.total_extra + gbd.total_base AS Discount FROM tier_extra_discounts ted CROSS JOIN global_base_discount gbd;
方法二:用窗口函数简化实现
如果偏好窗口函数写法,可以通过全局窗口计算基础折扣,再结合分组求和:
SELECT Stretch, FromUnit, SUM(Discount) + MAX(global_base) OVER () AS Discount FROM ( SELECT *, -- 计算全局范围内Default+Bonus的折扣总和 SUM(CASE WHEN DiscType IN ('Default', 'Bonus') THEN Discount ELSE 0 END) OVER () AS global_base FROM your_table ) t -- 仅针对Extra类型的折扣记录进行分组 WHERE DiscType = 'Extra' GROUP BY Stretch, FromUnit, global_base;
你的原查询为何出错?
你之前用sum over (partition by stretch)会把每个Stretch下的所有折扣(包括Default、Bonus、Extra)直接求和,但Default和Bonus是全局适用的,并非只属于Stretch1,所以这两个折扣没有被加到Stretch2和Stretch3的结果中,最终数值自然不符合预期。
以上两种方法运行后,都会得到你期望的结果:
| Stretch | FromUnit | Discount |
|---|---|---|
| 1 | 0 | 25 |
| 2 | 7 | 27 |
| 3 | 10 | 30 |
内容的提问来源于stack exchange,提问作者Desk
相关产品推荐
相关产品推荐

