SQL/Python如何对比相邻月份分组差异 查找当月新增分组
需求实现方案
难度说明
这个需求直接用SQL实现难度极低,完全不需要导出CSV后用pandas处理,直接在数据库端计算省去了数据导出、加载的冗余步骤,数据量越大效率优势越明显。
你提到的LAG窗口函数思路完全可行,另外用NOT EXISTS关联的写法兼容性更强、逻辑更直观,两种方案都可以快速实现需求。
前置注意事项
你原来生成#Groupings临时表时用了WITH ROLLUP,会生成GroupNumber为NULL的汇总行,计算新增分组前需要先把这部分无效数据过滤掉,避免结果错误。
另外如果你的业务数据跨自然年,不要直接用MONTH(PaymentDate)提取的数字月份做相邻判断,建议先格式化为YYYYMM格式的年月维度值(比如2022年1月存为202201,2022年12月存为202212,2023年1月存为202301),避免出现1月的上一个月被判定为0的逻辑错误。
具体SQL写法
写法1:基于LAG窗口函数实现
基于你已经生成的#Groupings临时表,直接写后续逻辑即可:
WITH Group_Appear_Log AS ( SELECT GroupNumber, Payment_Month, -- 取每个分组上一次出现的月份 LAG(Payment_Month, 1) OVER (PARTITION BY GroupNumber ORDER BY Payment_Month) AS Last_Appear_Month FROM #Groupings WHERE GroupNumber IS NOT NULL -- 过滤ROLLUP生成的汇总空行 ) SELECT DISTINCT GroupNumber FROM Group_Appear_Log WHERE Last_Appear_Month IS NULL -- 分组首次出现,即之前月份从未出现过 AND Payment_Month = 3 -- 这里替换成你要统计的目标月份,示例中统计3月新增就写3
针对你给出的示例数据,运行后会返回3333、3334两个分组,和预期结果完全一致。
写法2:基于NOT EXISTS关联实现(兼容性更好)
如果你的数据库版本不支持窗口函数,可以用关联判断的写法,逻辑更直白:
SELECT DISTINCT curr.GroupNumber FROM #Groupings curr WHERE curr.GroupNumber IS NOT NULL AND curr.Payment_Month = 3 -- 替换为目标统计月份 -- 排除掉在上一个月已经出现过的分组 AND NOT EXISTS ( SELECT 1 FROM #Groupings prev WHERE prev.GroupNumber = curr.GroupNumber AND prev.Payment_Month = curr.Payment_Month - 1 AND prev.GroupNumber IS NOT NULL )
pandas方案补充说明
如果是极小体量的数据集(十万行级别以内),用pandas确实也能实现需求,但属于冗余操作:你需要额外完成数据导出、文件加载、去重、相邻行判断的步骤,流程更长;如果数据量达到百万级以上,pandas会占用大量本地内存,执行效率远不如数据库端直接计算。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

