如何在不使用游标时查询同一PK下间隔12个月的记录?
问题描述
我有一张包含PK(主键)和Created_Date(创建日期)的表,数据如下:
| PK | Created_Date |
|---|---|
| 1 | 01/01/2007 |
| 1 | 01/02/2007 |
| 1 | 12/12/2008 |
| 2 | 15/02/2021 |
| 2 | 01/06/2022 |
| 2 | 02/06/2022 |
我希望筛选出同一PK下创建日期间隔至少12个月的记录,例如:
- PK为1时,预期返回第1行和第3行
- PK为2时,预期返回第1行和第2行
部分PK可能存在多年跨度的多个创建日期,请问是否有不使用游标实现该需求的方法?
解决方案:用递归CTE实现(无需游标)
可以通过递归CTE(公共表表达式)逐行筛选符合条件的记录,核心逻辑是从每个PK的第一条记录开始,依次寻找下一个与上一条选中日期间隔至少12个月的记录。
示例SQL代码(以SQL Server为例)
WITH SortedData AS ( -- 给每个PK的记录按创建日期排序,添加行号 SELECT PK, Created_Date, ROW_NUMBER() OVER (PARTITION BY PK ORDER BY Created_Date) AS RowNum FROM YourTableName ), RecursiveCTE AS ( -- 起始:选中每个PK的第一条记录 SELECT PK, Created_Date, RowNum FROM SortedData WHERE RowNum = 1 UNION ALL -- 递归:寻找下一个与上一条选中日期间隔≥12个月的最早记录 SELECT sd.PK, sd.Created_Date, sd.RowNum FROM SortedData sd INNER JOIN RecursiveCTE rc ON sd.PK = rc.PK AND sd.RowNum > rc.RowNum AND DATEDIFF(MONTH, rc.Created_Date, sd.Created_Date) >= 12 -- 确保只选符合条件的最早那条,避免重复选中 WHERE NOT EXISTS ( SELECT 1 FROM SortedData sd2 WHERE sd2.PK = sd.PK AND sd2.RowNum > rc.RowNum AND sd2.RowNum < sd.RowNum AND DATEDIFF(MONTH, rc.Created_Date, sd2.Created_Date) >= 12 ) ) SELECT PK, Created_Date FROM RecursiveCTE ORDER BY PK, Created_Date;
代码说明
- SortedData:先对每个PK的记录按创建日期排序并添加行号,方便后续按顺序遍历。
- RecursiveCTE:
- 起始部分:把每个PK的第一条记录作为筛选起点,这是必选的。
- 递归部分:关联上一轮选中的记录,找到下一个日期与上一条间隔满12个月的记录,同时通过
NOT EXISTS确保只选中符合条件的最早那条,避免同一PK里出现多余的记录(比如PK2中的02/06/2022和上一条间隔不足12个月,就不会被选中)。
适配其他数据库
如果用MySQL 8.0+,只需把日期差函数替换为TIMESTAMPDIFF(MONTH, rc.Created_Date, sd.Created_Date)即可,其他逻辑不变。
内容的提问来源于stack exchange,提问作者Joe1
相关产品推荐
相关产品推荐

