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

SQL中如何筛选重叠日期范围?排查查询语句失效问题

如何筛选出日期范围重叠的行

先把你的示例数据整理成更清晰的表格,方便我们分析问题:

sIDstart_dateend_date行号
11995-07-282003-07-201
12003-07-212010-05-042
12010-05-032010-05-033
21960-01-012011-03-014
22011-03-022012-03-135
22012-03-122012-10-216
22012-10-222012-11-087
32003-07-232010-05-028

你的需求是找出同一sID下日期范围存在重叠的行,比如sID=1的第2、3行(第2行的日期范围完全包含第3行),以及sID=2的第5、6行(两者日期有交集)。

你之前的SQL没排除第1行的原因

大概率是你的筛选条件没精准区分「相邻日期」和「重叠日期」。比如sID=1的第1行end_date是2003-07-20,第2行start_date是2003-07-21,这属于相邻但不重叠,如果你的条件只写了a.end_date >= b.start_date这类单一限制,就会误把这种相邻情况当成重叠,从而把第1行也包含进来。

正确的SQL写法

要准确筛选重叠行,核心是明确重叠的判断逻辑:同一sID下的两行A和B,日期范围存在交集的条件是:A.start_date <= B.end_date AND A.end_date >= B.start_date。同时要避免匹配行自身和重复结果(比如A匹配B和B匹配A)。

这里提供两种实用的实现方式:

方式1:自连接+去重

SELECT DISTINCT t1.*
FROM your_table t1
JOIN your_table t2 
  ON t1.sID = t2.sID
  AND t1.rowid != t2.rowid -- 用主键/rowid排除同一行,根据你的表结构调整
  AND t1.start_date <= t2.end_date
  AND t1.end_date >= t2.start_date
-- 如果只需要sID=1的重叠行,加上下面的WHERE条件
WHERE t1.sID = 1

方式2:窗口函数(适用于MySQL 8+/PostgreSQL/Oracle等)

用LEAD/LAG窗口函数直接对比当前行和相邻行的日期:

WITH ranked_data AS (
  SELECT 
    *,
    LEAD(start_date) OVER (PARTITION BY sID ORDER BY start_date) AS next_start,
    LAG(end_date) OVER (PARTITION BY sID ORDER BY start_date) AS prev_end
  FROM your_table
)
SELECT sID, start_date, end_date
FROM ranked_data
WHERE 
  -- 当前行与上一行重叠
  (prev_end IS NOT NULL AND start_date <= prev_end)
  -- 或者当前行与下一行重叠
  OR (next_start IS NOT NULL AND end_date >= next_start)

针对你的精准需求(仅返回sID=1的第2、3行)

如果只需要这两行,可以用EXISTS子查询精准过滤:

SELECT t1.*
FROM your_table t1
WHERE t1.sID = 1
AND EXISTS (
  SELECT 1
  FROM your_table t2
  WHERE t2.sID = t1.sID
  AND t2.rowid != t1.rowid
  AND t1.start_date <= t2.end_date
  AND t1.end_date >= t2.start_date
)

这个查询会自动排除第1行(因为它和sID=1的其他行没有日期重叠),只返回存在重叠的第2、3行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:53:15