You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle中重叠促销日期范围拆分及累计折扣计算问题

问题拆分与促销价格计算解决方案

现有一商品原价为229,存在以下重叠促销活动:

Start_dateEnd DateDiscount_pecentOriginal_Retail
10-Dec-2314-Dec-2310229
12-Dec-2316-Dec-2320229

需要拆分为如下格式(重叠期需累计计算折扣:先10%再20%):

Start_dateEnd DateDiscount_pecentOriginal_RetailPromo_Retail
10-Dec-2311-Dec-2310229206.1
12-Dec-2314-Dec-2320229164.8 (20% applied on 206.1)
15-Dec-2316-Dec-2320229183.2 (10% applied on 229)

你已通过SQL完成日期拆分,但无法计算Promo_Retail字段,以下是补充完整逻辑的实现:

WITH cte_markers AS (
    -- 提取所有促销的起始、结束+1日期作为区间分割点
    SELECT start_date AS marker_date FROM Table_A
    UNION
    SELECT end_date + 1 AS marker_date FROM Table_A
),
cte_date_ranges AS (
    -- 生成连续无重叠的日期区间
    SELECT 
        marker_date AS start_date,
        LEAD(marker_date) OVER (ORDER BY marker_date) - 1 AS end_date
    FROM cte_markers
    WHERE LEAD(marker_date) OVER (ORDER BY marker_date) IS NOT NULL
),
cte_active_promos AS (
    -- 关联区间与生效的促销,计算累计折扣和说明文本
    SELECT 
        dr.start_date,
        dr.end_date,
        ta.Discount_pecent,
        ta.Original_Retail,
        -- 计算累计折扣后的最终价格(用EXP+SUM+LN替代PRODUCT,兼容多数数据库)
        ta.Original_Retail * EXP(SUM(LN(1 - ta.Discount_pecent / 100.0)) OVER (PARTITION BY dr.start_date, dr.end_date)) AS final_price,
        -- 生成折扣应用的说明链
        STRING_AGG(
            CONCAT(ta.Discount_pecent, '% applied on ', 
                   ROUND(ta.Original_Retail * EXP(SUM(LN(1 - t2.Discount_pecent / 100.0)) OVER (PARTITION BY dr.start_date, dr.end_date ORDER BY t2.Discount_pecent ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)), 1)),
            ' then '
        ) OVER (PARTITION BY dr.start_date, dr.end_date ORDER BY ta.Discount_pecent) AS price_note
    FROM cte_date_ranges dr
    JOIN Table_A ta 
        ON dr.start_date <= ta.End_Date AND dr.end_date >= ta.Start_date
),
cte_final AS (
    -- 聚合区间结果,匹配示例输出格式
    SELECT 
        start_date,
        end_date,
        MAX(Discount_pecent) AS Discount_pecent,
        MAX(Original_Retail) AS Original_Retail,
        CONCAT(ROUND(final_price, 1), 
               CASE WHEN COUNT(*) OVER (PARTITION BY start_date, end_date) > 1 THEN 
                   CONCAT(' (', LAST_VALUE(price_note) OVER (PARTITION BY start_date, end_date), ')') 
               ELSE '' END) AS Promo_Retail
    FROM cte_active_promos
    GROUP BY start_date, end_date, final_price
)
SELECT * FROM cte_final ORDER BY start_date;

关键逻辑说明:

  • 区间分割:通过cte_markers提取所有促销的时间节点,用LEAD生成连续无重叠的日期区间。
  • 累计折扣计算:用EXP(SUM(LN(折扣系数)))替代部分数据库不支持的PRODUCT函数,实现折扣的累计相乘。
  • 说明文本生成:通过窗口函数的STRING_AGG和LAST_VALUE,拼接出折扣应用的递进说明,匹配示例格式。

内容的提问来源于stack exchange,提问作者Amit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:17:35