SQL按时间范围查询时如何额外包含起始时间前的最近一行?
解决思路与对应SQL
核心逻辑是合并两个结果集返回:符合目标时间范围的数据集 + 起始时间之前的最近一条数据,两个数据集无重叠,无需额外去重处理。
前置参数定义
- 起始时间:
@start_time = 14 - 结束时间:
@end_time = 65 - 目标表名:
test_table
最简洁的单查询写法(兼容所有主流数据库,性能最优)
无需UNION拼接,直接通过子查询确定查询下限即可:
SELECT * FROM test_table WHERE time <= @end_time AND time >= ( SELECT COALESCE(MAX(time), @start_time) FROM test_table WHERE time < @start_time ) ORDER BY time ASC;
逻辑说明
- 子查询先找到所有小于起始时间的行中的最大时间值,就是起始时间之前的最近一行的时间
- 用
COALESCE做边界兼容:如果不存在早于起始时间的行,就直接用起始时间作为查询下限 - 最终查询所有介于计算出的下限和结束时间之间的行,返回结果自然包含你需要的额外行
- 如果
time字段建了索引,该写法可以直接命中索引,不需要全表扫描,性能很高
代入你提供的示例参数执行,返回结果和你预期的完全一致。
基于UNION的兼容写法(适配不支持复杂子查询的低版本数据库)
如果你的数据库版本较低,不支持上述子查询写法,可以用UNION拼接两个结果集:
-- 取起始时间之前最近的一行 SELECT * FROM test_table WHERE time < @start_time ORDER BY time DESC LIMIT 1 UNION ALL -- 取时间范围内的所有行 SELECT * FROM test_table WHERE time BETWEEN @start_time AND @end_time ORDER BY time ASC;
不同数据库的取第一行语法可以自行替换:SQL Server用TOP 1,Oracle用FETCH FIRST 1 ROW ONLY。
内容的提问来源于stack exchange,提问作者user1179317
相关产品推荐
相关产品推荐

