You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server遍历日期并排除7天内重复日期的实现方法

SQL Server 实现日期间隔7天内仅保留最早记录的方案

假设你的数据表结构类似 CustomerVisits,包含 CustomerName(客户名称)和 VisitDate(访问日期)两个核心字段,以下提供两种可行的实现方案:

方案1:使用LAG窗口函数标记需排除的记录

利用窗口函数 LAG() 获取同一客户的上一条访问日期,通过计算日期差判断是否保留当前记录,逻辑简单高效:

WITH RankedVisits AS (
    SELECT 
        CustomerName,
        VisitDate,
        -- 获取同一客户的上一条访问日期
        LAG(VisitDate) OVER (PARTITION BY CustomerName ORDER BY VisitDate) AS PreviousVisitDate,
        -- 标记是否保留:第一条记录默认保留,后续记录与上一条间隔≥7天则保留
        CASE 
            WHEN LAG(VisitDate) OVER (PARTITION BY CustomerName ORDER BY VisitDate) IS NULL THEN 1
            WHEN DATEDIFF(day, LAG(VisitDate) OVER (PARTITION BY CustomerName ORDER BY VisitDate), VisitDate) >= 7 THEN 1
            ELSE 0
        END AS KeepFlag
    FROM CustomerVisits
)
-- 输出所有记录及标记,如需仅保留有效记录可添加 WHERE KeepFlag = 1
SELECT 
    CustomerName,
    VisitDate,
    KeepFlag
FROM RankedVisits
ORDER BY CustomerName, VisitDate;

逻辑说明:

  • 按客户分组、访问日期升序排序后,LAG() 函数会返回当前记录的上一条同客户记录的日期
  • 第一条记录因无前置记录,直接标记为保留(KeepFlag=1)
  • 后续记录若与上一条的间隔≥7天则保留,否则标记为排除(KeepFlag=0)

方案2:递归CTE筛选所有符合条件的保留记录

如果需要跳过所有7天内的中间记录,直接筛选出所有间隔≥7天的有效记录(比如客户有2023/10/22、2023/10/25、2023/11/1三条记录,仅保留2023/10/22和2023/11/1),可以用递归CTE实现:

WITH CustomerFirstVisit AS (
    -- 先获取每个客户的最早访问日期
    SELECT 
        CustomerName,
        MIN(VisitDate) AS VisitDate
    FROM CustomerVisits
    GROUP BY CustomerName
),
RecursiveVisits AS (
    -- 递归起始点:每个客户的最早记录
    SELECT 
        CustomerName,
        VisitDate
    FROM CustomerFirstVisit
    UNION ALL
    -- 递归查找下一条与当前记录间隔≥7天的最早日期
    SELECT 
        cv.CustomerName,
        MIN(cv.VisitDate) AS VisitDate
    FROM CustomerVisits cv
    JOIN RecursiveVisits rv ON cv.CustomerName = rv.CustomerName
    WHERE cv.VisitDate > rv.VisitDate 
      AND DATEDIFF(day, rv.VisitDate, cv.VisitDate) >= 7
    GROUP BY cv.CustomerName
)
-- 关联原表标记所有记录的保留状态
SELECT 
    cv.CustomerName,
    cv.VisitDate,
    CASE WHEN rv.VisitDate IS NOT NULL THEN 1 ELSE 0 END AS KeepFlag
FROM CustomerVisits cv
LEFT JOIN RecursiveVisits rv ON cv.CustomerName = rv.CustomerName AND cv.VisitDate = rv.VisitDate
ORDER BY cv.CustomerName, cv.VisitDate;

逻辑说明:

  • 首先获取每个客户的最早访问日期作为递归起点
  • 递归阶段不断查找当前保留记录之后、间隔≥7天的最早访问日期,直到没有符合条件的记录为止
  • 最后通过左关联原表,标记哪些记录是需要保留的

内容的提问来源于stack exchange,提问作者Aqua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 09:25:28