如何用SQL计算一周内售出商品的占比?是否需使用子查询?
计算一周内售出商品的百分比:SQL实现方案
嘿,这个需求我帮你捋清楚,咱们一步步来解决~首先得明确核心逻辑:我们需要先把每个商品的上架时间(action='created')和售出时间(action='sold')匹配起来,然后计算时间差≤7天的商品占比。至于要不要用子查询?答案是:不是必须,但用子查询(或CTE)能让逻辑更清晰,当然也可以用自连接实现。
核心思路
每个商品的上架和售出是两条独立的记录,所以第一步要把同一个item_id的这两条记录关联起来,计算时间差;第二步根据你的统计口径(是占已售出商品的比例,还是占所有上架商品的比例)计算百分比。
方案1:用自连接实现(无需子查询)
统计口径:一周内售出的商品占已售出商品的百分比
SELECT ROUND( 100.0 * COUNT(CASE WHEN DATEDIFF(s.date, c.date) <= 7 THEN 1 END) / COUNT(s.item_id), 2 ) AS weekly_sold_percentage FROM your_table c JOIN your_table s ON c.item_id = s.item_id WHERE c.action = 'created' AND s.action = 'sold';
- 解释:把表自连接,
c代表上架记录,s代表售出记录,通过item_id关联;用DATEDIFF计算售出和上架的天数差,统计满足≤7天的数量,除以总售出商品数得到百分比,ROUND用来保留两位小数。 - 对应你的样本数据:已售出商品是1和2,其中仅商品1的间隔(6天)符合要求,结果为50.00%。
统计口径:一周内售出的商品占所有上架商品的百分比
如果要把没售出的商品也纳入分母统计,用LEFT JOIN:
SELECT ROUND( 100.0 * COUNT(CASE WHEN DATEDIFF(s.date, c.date) <= 7 THEN 1 END) / COUNT(c.item_id), 2 ) AS weekly_sold_percentage FROM your_table c LEFT JOIN your_table s ON c.item_id = s.item_id AND s.action = 'sold' WHERE c.action = 'created';
- 解释:
LEFT JOIN会保留所有上架记录,哪怕该商品没有售出记录;分母是所有上架商品数(样本中是3个),分子是一周内售出的商品数(1个),结果约为33.33%。
方案2:用子查询/CTE实现(逻辑更清晰)
如果觉得自连接的逻辑有点绕,可以用CTE(公共表表达式,本质是一种子查询)先把每个商品的上架、售出时间整合到一行,再计算:
WITH item_actions AS ( SELECT item_id, MAX(CASE WHEN action = 'created' THEN date END) AS created_date, MAX(CASE WHEN action = 'sold' THEN date END) AS sold_date FROM your_table GROUP BY item_id ) SELECT ROUND( -- 这里可以根据需求切换分母: -- 1. 占已售出商品的比例:COUNT(CASE WHEN sold_date IS NOT NULL THEN 1 END) -- 2. 占所有上架商品的比例:COUNT(item_id) 100.0 * COUNT(CASE WHEN DATEDIFF(sold_date, created_date) <=7 THEN 1 END) / COUNT(CASE WHEN sold_date IS NOT NULL THEN 1 END), 2 ) AS weekly_sold_percentage FROM item_actions;
- 解释:先通过
GROUP BY item_id聚合每个商品的关键时间,再基于这个中间表计算百分比,逻辑更直观,后续修改统计口径也更方便。
关于子查询的必要性
子查询不是必须的,但当数据逻辑复杂、需要多次复用中间结果时,用子查询/CTE能让代码更易读、更易维护。如果只是简单的统计,自连接的写法也完全可行。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

