在Microsoft SQL Server中忽略秒数按分钟匹配时间列实现表连接
在SQL Server中忽略秒数实现两表左连接的方法
要让同一分钟内的时间(无论秒和毫秒数值)成功匹配,你可以通过以下几种方式修改连接条件:
方法一:用DATEADD+DATEDIFF截断到分钟(性能最优,推荐)
这种写法属于SARGable表达式,若时间列存在索引,能最大程度利用索引提升查询效率,是处理时间截断的高效方案:
SELECT * FROM t1 LEFT JOIN t2 ON DATEADD(MINUTE, DATEDIFF(MINUTE, 0, t1.[TimeCol]), 0) = DATEADD(MINUTE, DATEDIFF(MINUTE, 0, t2.[TimeCol]), 0)
原理:DATEDIFF(MINUTE, 0, TimeCol)计算从0时间点到目标时间的总分钟数,再通过DATEADD将该分钟数还原为时间,自动清零秒和毫秒部分,最终得到截断到分钟的统一时间值。
方法二:转换为字符串截断到分钟
通过将时间转换为仅包含年-月-日 时:分的字符串进行匹配,写法更直观,但属于非SARGable表达式,大数据量场景下性能会受影响:
SELECT * FROM t1 LEFT JOIN t2 ON CONVERT(VARCHAR(16), t1.[TimeCol], 120) = CONVERT(VARCHAR(16), t2.[TimeCol], 120)
原理:样式代码120对应格式yyyy-MM-dd HH:mm:ss,截取前16个字符即可得到仅保留到分钟的时间字符串。
方法三:用FORMAT函数格式化时间(SQL Server 2012及以上版本适用)
如果使用SQL Server 2012或更高版本,也可以用FORMAT函数直接格式化到分钟,同样性能不如方法一:
SELECT * FROM t1 LEFT JOIN t2 ON FORMAT(t1.[TimeCol], 'yyyy-MM-dd HH:mm') = FORMAT(t2.[TimeCol], 'yyyy-MM-dd HH:mm')
大数据量下的性能优化方案
若表数据量较大,建议创建持久化计算列并添加索引,避免每次连接时重复计算时间截断值:
-- 为t1表添加截断到分钟的持久化计算列 ALTER TABLE t1 ADD TimeCol_Minute AS DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [TimeCol]), 0) PERSISTED; -- 为t2表添加同样的计算列 ALTER TABLE t2 ADD TimeCol_Minute AS DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [TimeCol]), 0) PERSISTED; -- 为计算列创建非聚集索引 CREATE NONCLUSTERED INDEX IX_t1_TimeCol_Minute ON t1(TimeCol_Minute); CREATE NONCLUSTERED INDEX IX_t2_TimeCol_Minute ON t2(TimeCol_Minute); -- 使用计算列执行连接查询 SELECT * FROM t1 LEFT JOIN t2 ON t1.TimeCol_Minute = t2.TimeCol_Minute;
内容的提问来源于stack exchange,提问作者Emre Oz
相关产品推荐
相关产品推荐

