如何查找多组键值元素中相同id与name的重叠时间切片
查找存在时间重叠的id+name组合
要找出所有id和name相同且对应的时间切片(validFrom到validTo)存在重叠的组合,我整理了两种实用的SQL解决方案,适合不同场景需求:
方法1:自连接查询(直观易懂)
这是最直接的实现方式,通过将表与自身连接,精准匹配同一id+name的记录,同时判断时间区间是否重叠:
SELECT DISTINCT t1.id, t1.name FROM your_table t1 JOIN your_table t2 ON t1.id = t2.id AND t1.name = t2.name AND t1.validFrom < t2.validTo AND t2.validFrom < t1.validTo AND t1.value != t2.value; -- 若表有唯一主键,建议用主键替换value来排除自匹配
逻辑拆解:
t1.id = t2.id AND t1.name = t2.name:确保只对比同一id+name分组内的记录- 时间重叠判断公式:
t1.validFrom < t2.validTo AND t2.validFrom < t1.validTo,这是判断两个区间[A_start, A_end]和[B_start, B_end]是否重叠的通用规则 t1.value != t2.value:避免同一条记录和自身连接(如果表有主键比如row_id,用t1.row_id != t2.row_id会更严谨)
方法2:窗口函数(性能更优)
如果数据量较大,用窗口函数的执行效率会更高,通过排序后对比相邻记录的时间区间即可:
WITH sorted_records AS ( SELECT id, name, validFrom, validTo, -- 获取同id+name组中,上一条记录的validTo LAG(validTo) OVER (PARTITION BY id, name ORDER BY validFrom) AS prev_end FROM your_table ) SELECT DISTINCT id, name FROM sorted_records -- 当前记录的开始时间早于上一条的结束时间,说明存在重叠 WHERE validFrom < prev_end;
逻辑拆解:
- 先按
id和name分组,每组内按validFrom升序排序 - 用
LAG()函数获取每组中上一条记录的validTo - 如果当前记录的
validFrom小于上一条的validTo,则两个时间区间存在重叠,标记该id+name组合
最终输出结果
针对你提供的示例数据,两种方法都会得到如下结果:
| id | name |
|---|---|
| 2 | c |
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

