SQL Server非连续计数报告求助:实现计数重置与重新累加逻辑
解决思路与SQL实现
你的需求核心是按客户追踪连续未取件的次数,取件后重置计数,最终得到每个客户的当前累计未取件数。原来的SQL只做了简单的条件求和,没法处理“重置后重新累加”的逻辑,这里需要用窗口函数来划分客户的取件周期,再在每个周期内计数。
核心逻辑拆解
- 划分取件周期:对每个客户,按日期排序,每次遇到取件(
DeliveryCode=1)就标记一个新的周期——这样同一个周期内的记录都是两次取件之间的未取件记录,或者取件前的未取件记录。 - 周期内计数:在每个周期里,对未取件的记录按日期顺序累加计数,取件记录直接计0。
- 取最终计数:每个客户的最终计数取其最新一条记录对应的周期内计数即可。
完整SQL实现
假设你的表名为delivery_records,字段为Customer_id、DATE、DeliveryCode,可以用以下SQL实现:
WITH customer_cycles AS ( SELECT Customer_id, DATE, DeliveryCode, -- 累计取件次数,作为周期ID:每次取件后周期ID+1,实现计数重置 SUM(CASE WHEN DeliveryCode = 1 THEN 1 ELSE 0 END) OVER ( PARTITION BY Customer_id ORDER BY DATE ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS cycle_id FROM delivery_records ), running_counts AS ( SELECT Customer_id, DATE, DeliveryCode, cycle_id, -- 每个周期内,未取件记录按日期递增加1,取件记录计0 CASE WHEN DeliveryCode = 2 THEN ROW_NUMBER() OVER ( PARTITION BY Customer_id, cycle_id ORDER BY DATE ) ELSE 0 END AS current_count FROM customer_cycles ) -- 获取每个客户最新记录的计数作为最终结果 SELECT Customer_id, MAX(CASE WHEN DATE = latest_date THEN current_count ELSE 0 END) AS final_unclaimed_count FROM ( SELECT Customer_id, DATE, current_count, MAX(DATE) OVER (PARTITION BY Customer_id) AS latest_date FROM running_counts ) t GROUP BY Customer_id;
对示例数据的验证
用你提供的示例数据测试,会得到完全符合预期的结果:
- Customer_id 1:三次未取件,最终计数3
- Customer_id 2/3:全程取件,最终计数0
- Customer_id 4:前两次未取件,第三次取件重置计数,最终计数0
补充说明
- 你原来SQL里的
WHEN Customer_id <> Customer_id THEN 1是无效逻辑(永远不会触发),可以直接删除。 - 大部分主流数据库(MySQL 8+、PostgreSQL、SQL Server等)都支持这段代码里的窗口函数语法。
内容的提问来源于stack exchange,提问作者pete
相关产品推荐
相关产品推荐

