You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SQL Server中如何在窗口函数中运用日期范围筛选数据?

解决SQL Server中按每个ID的最新日期筛选前30天数据的问题

你需要从给定的数据表中,为每个id筛选出其最新日期往前30天内的所有记录,由于数据存在日期缺失,且SQL Server不支持窗口函数中的日期范围逻辑(比如RANGE BETWEEN INTERVAL '30 day' PRECEDING AND CURRENT ROW这类语法),这里提供一个可行的解决方案。

先把你的示例数据表整理成清晰的格式:

iddateitem
12307/01/2018anf
12331/12/2017sh
12301/01/2018ab
12312/03/2018fhy
12302/01/2018fg
12410/12/2017ab
12403/03/2017sh
12521/11/2017ab
12531/12/2017sh
12501/03/2017ab
12631/12/2017ab

方案思路

核心思路是先获取每个id的最新日期,再将这个最新日期与原表关联,筛选出该id下所有日期在「最新日期 - 30天」范围内的记录。这种方法不需要依赖窗口函数的日期范围特性,完全兼容SQL Server。

具体SQL代码

可以用CTE(公共表表达式)来实现,代码清晰易读:

WITH IdLatestDates AS (
    -- 第一步:获取每个id的最新日期
    SELECT 
        id,
        MAX(CONVERT(DATE, date, 103)) AS latest_date  -- 转换dd/mm/yyyy格式为DATE类型
    FROM your_table_name
    GROUP BY id
)
-- 第二步:关联原表,筛选符合日期范围的记录
SELECT 
    t.id,
    t.date,
    t.item
FROM your_table_name t
JOIN IdLatestDates ld ON t.id = ld.id
WHERE 
    CONVERT(DATE, t.date, 103) >= DATEADD(DAY, -30, ld.latest_date)
ORDER BY t.id, CONVERT(DATE, t.date, 103) DESC;

代码解释

  1. CTE部分IdLatestDates通过GROUP BY idMAX()函数,得到每个id对应的最晚日期。这里用CONVERT(DATE, date, 103)是因为你的日期格式是dd/mm/yyyy,103是SQL Server对应欧洲日期格式的转换代码,如果你的date字段本身就是DATE类型,可以直接去掉转换。
  2. 关联筛选部分:将原表与CTE通过id关联,用DATEADD(DAY, -30, ld.latest_date)计算出每个id的筛选起始日期,然后保留原表中日期大于等于该起始日期的记录。
  3. 排序:最后按id和日期降序排列,方便查看每个id的最新记录在前。

补充说明

如果你的date字段是标准的DATEDATETIME类型,直接简化代码即可:

WITH IdLatestDates AS (
    SELECT 
        id,
        MAX(date) AS latest_date
    FROM your_table_name
    GROUP BY id
)
SELECT 
    t.id,
    t.date,
    t.item
FROM your_table_name t
JOIN IdLatestDates ld ON t.id = ld.id
WHERE 
    t.date >= DATEADD(DAY, -30, ld.latest_date)
ORDER BY t.id, t.date DESC;

这样就能准确筛选出每个id从最新日期往前30天内的所有数据,即使存在日期缺失也不受影响。

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

火山引擎 最新活动