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

如何选取两日期区间内的行并包含每行的前后行(若存在)

解决方案:筛选目标日期区间行及相邻行

嘿,这个需求用窗口函数就能完美解决!核心思路是先给每行标记是否在目标日期范围内,同时拿到同一用户下的前一行和后一行日期,最后筛选出「目标行」「目标行的前一行」「目标行的后一行」这三类数据。

原数据表

IDPersonIDDate
112017-04-01
212017-04-15
312017-05-13
412017-06-15
512017-08-13
612017-10-02
722017-05-04
822017-09-16
932017-04-23
1032017-07-06
1142017-06-01

期望结果表

IDPersonIDDate
212017-04-15
312017-05-13
412017-06-15
512017-08-13
612017-10-02
722017-05-04
822017-09-16
932017-04-23
1032017-07-06
1142017-06-01

实现SQL

WITH marked_records AS (
    SELECT 
        ID,
        PersonID,
        Date,
        -- 标记当前行是否在目标日期区间内
        CASE WHEN Date BETWEEN '2017-05-01' AND '2017-08-26' THEN 1 ELSE 0 END AS is_target_row,
        -- 获取同一用户的上一行日期
        LAG(Date) OVER (PARTITION BY PersonID ORDER BY Date) AS prev_row_date,
        -- 获取同一用户的下一行日期
        LEAD(Date) OVER (PARTITION BY PersonID ORDER BY Date) AS next_row_date
    FROM your_table_name -- 替换成你的实际表名
)
SELECT ID, PersonID, Date
FROM marked_records
WHERE 
    -- 条件1:当前行本身在目标区间内
    is_target_row = 1
    -- 条件2:当前行的下一行在目标区间内(即当前行是目标行的前一行)
    OR next_row_date BETWEEN '2017-05-01' AND '2017-08-26'
    -- 条件3:当前行的上一行在目标区间内(即当前行是目标行的后一行)
    OR prev_row_date BETWEEN '2017-05-01' AND '2017-08-26'
ORDER BY PersonID, Date;

逻辑解释

  1. CTE标记阶段:用LAG和LEAD窗口函数,按PersonID分组、Date排序,拿到每行的前后行日期;同时用CASE标记当前行是否在目标日期区间。
  2. 筛选阶段:只要满足三个条件中的任意一个,就保留该行:
    • 当前行是目标区间内的行
    • 当前行的下一行是目标行(需要把目标行的前一行也带上)
    • 当前行的上一行是目标行(需要把目标行的后一行也带上)

这样就能精准得到你想要的结果啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:57:52