当前位置: 首页 > article >正文

SQL题目分析:打折日期交叉问题--计算品牌总优惠天数

        在电商平台的数据分析中,处理品牌促销活动的日期交叉问题是一个挑战。本文将介绍几种高级SQL技巧,用于准确计算每个品牌的总优惠天数,即使在存在日期交叉的情况下。

问题背景

        我们有一个促销活动表 shop_discount,记录了不同品牌的促销开始日期和结束日期。目标是计算每个品牌的总优惠天数,同时确保同一天内的多个优惠活动只计算一次。

如下为平台商品促销数据:字段为品牌,打折开始日期,打折结束日期
brand stt        edt
oppo,2021-06-05,2021-06-09
oppo,2021-06-11,2021-06-21
vivo,2021-06-05,2021-06-15
vivo,2021-06-09,2021-06-21
redmi,2021-06-05,2021-06-21
redmi,2021-06-09,2021-06-15
redmi,2021-06-17,2021-06-26
huawei,2021-06-05,2021-06-26
huawei,2021-06-09,2021-06-15
huawei,2021-06-17,2021-06-21

计算每个品牌总的打折销售天数,注意其中的交叉日期,比如 vivo 品牌
第一次活动时间为 2021-06-05 到 2021-06-15,第二次活动时间为 2021-06-09 到 2021-06-21 其中 9 号到 15号为重复天数,
只统计一次,即 vivo 总打折天数为 2021-06-05 到 2021-06-21 共计 17 天。

示例数据

1.建表

create table shop_discount(
    brand string,
    stt string,
    edt string
);

2.导入数据

INSERT INTO shop_discount (brand, stt, edt) VALUES
('oppo', '2021-06-05', '2021-06-09'),
('oppo', '2021-06-11', '2021-06-21'),
('vivo', '2021-06-05', '2021-06-15'),
('vivo', '2021-06-09', '2021-06-21'),
('redmi', '2021-06-05', '2021-06-21'),
('redmi', '2021-06-09', '2021-06-15'),
('redmi', '2021-06-17', '2021-06-26'),
('huawei', '2021-06-05', '2021-06-26'),
('huawei', '2021-06-09', '2021-06-15'),
('huawei', '2021-06-17', '2021-06-21');

 3.查询数据是否导入成功

select * from shop_discount;

高级SQL技巧

方法1:使用开窗进行连续区间划分及合并

这种方法通过识别每个品牌的连续促销区间来计算总天数。

SELECT 
    brand,
    SUM(days) AS promotion_day_count
FROM (
    SELECT 
        brand, DATEDIFF(MAX(edt), MIN(stt)) + 1 AS days 
    FROM (
        SELECT 
            brand, stt, edt,
            SUM(is_new_start) OVER (PARTITION BY brand ORDER BY stt) AS interval_id
        FROM (
            SELECT 
                brand, stt, edt,
                IF(stt > COALESCE(LAG_END_DATE, '1970-01-01'), 1, 0) AS is_new_start
            FROM (
                SELECT 
                    brand, stt, edt,
                    MAX(edt) OVER (PARTITION BY brand ORDER BY stt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS LAG_END_DATE
                FROM 
                    shop_discount
            ) t1
        ) t2
    ) t3 
    GROUP BY brand, interval_id
) t4 
GROUP BY brand;

 

方法2:使用开窗求出没有活动的天数

这种方法通过计算每个促销区间之间的空白天数来调整总天数。

SELECT 
    brand,
    DATEDIFF(MAX(edt), MIN(stt)) - SUM(no_promo_days) + 1 AS promotion_day_count
FROM (
    SELECT 
        brand, stt, edt,
        IF(stt > LAG_END_DATE, DATEDIFF(stt, LAG_END_DATE) - 1, 0) AS no_promo_days
    FROM (
        SELECT 
            brand, stt, edt,
            MAX(edt) OVER (PARTITION BY brand ORDER BY stt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS LAG_END_DATE
        FROM 
            shop_discount
    ) t1
) t2 
GROUP BY brand;

 

方法3:使用开窗去除区间之间重复的部分

这种方法通过确保每个促销日期只被计算一次来计算总天数。

SELECT 
    brand, 
    SUM(DATEDIFF(edt, start_date) + 1) AS promotion_day_count
FROM (
    SELECT 
        brand, MAX_END_DATE,
        IF(MAX_END_DATE IS NULL OR stt > MAX_END_DATE, stt, DATE_ADD(MAX_END_DATE, 1)) AS start_date, edt
    FROM (
        SELECT 
            brand, stt, edt,
            MAX(edt) OVER (PARTITION BY brand ORDER BY stt ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS MAX_END_DATE
        FROM 
            shop_discount
    ) t1
) t2 
WHERE edt > start_date 
GROUP BY brand;

 

方法4:使用UDTF生成所有活动日期然后去重

这种方法通过生成所有可能的促销日期并去除重复来计算总天数。

SELECT 
    brand,
    COUNT(DISTINCT promo_date) AS promotion_day_count
FROM (
    SELECT 
        brand, DATE_ADD(stt, pos) AS promo_date 
    FROM 
        shop_discount
    LATERAL VIEW 
        POSEXPLODE(SPLIT(REPEAT(',', DATEDIFF(edt, stt)), ',')) tmp AS pos, element
) t1 
GROUP BY 
    brand;

 

结论

        这些高级SQL技巧提供了多种方法来处理促销日期交叉的问题,确保每个品牌的总优惠天数计算准确。选择合适的方法取决于具体的数据结构和性能要求。希望这些技巧能帮助你更好地管理和分析电商平台的促销活动数据。如果你有任何疑问或需要进一步的帮助,请随时联系。


http://www.kler.cn/a/307747.html

相关文章:

  • Qt 日志文件的滚动写入
  • 网络原理-网络层和数据链路层
  • 技术题总结
  • A3超级计算机虚拟机,为大型语言模型LLM和AIGC提供强大算力支持
  • 【缺陷检测】Anomaly Detection via Reverse Distillation from One-Class Embedding
  • ⾃动化运维利器Ansible-基础
  • DDD的主要流程
  • Gson转换
  • Matlab simulink建模与仿真 第十六章(用户定义函数库)
  • matlab边缘点提取函数
  • debian服务器上搭建git服务及添加文件提交拉取的操作记录、在Ubuntu上搭建Jenkins服务以及Ubuntu中的PPA源及PPA的安装使用
  • 【C++学习】 IO 流揭秘:高效数据读写的最佳实践
  • 1×4矩阵键盘详解(STM32)
  • 基于小程序的教学辅助微信小程序设计+ssm(lw+演示+源码+运行)
  • 在Flask中实现跨域请求(CORS)
  • 建模杂谈系列256 规则函数化改造
  • Kotlin:1.9.0 的新特性
  • 鸿萌数据恢复服务:如何恢复 Mac 系统中被擦除的文件?
  • 网络高级项目( 基于webserver的工业数据采集和控制项目)
  • Https AK--(ssl 安全感满满)
  • 【LIO】FAST-LIO论文详解
  • 如何在C++中使用mupdf操作pdf文件(一)
  • 微信小程序页面制作——婚礼邀请函(含代码)
  • 深入探讨ES6高级特性与实际应用
  • 注册登录案列
  • 加密