如何用SQL实现t1与t2匹配及无匹配时的前置日期匹配逻辑?
我来帮你搞定这个SQL匹配的问题,其实不用写复杂的循环,用窗口函数就能高效解决,而且代码更简洁易维护。下面是具体的实现思路和完整代码:
核心思路拆解
我们的目标是为t2的每条记录找到符合要求的t1数据,分三个核心步骤:
- 先关联t1和t2,筛选出完全匹配(t2.date = t1.date 且 t2.col1 = t1.col3)的记录
- 对没有完全匹配的t2记录,找到t1中日期早于t2.date且col3等于t2.col1的所有记录,取其中最近的日期那条
- 最后检查是否存在t2记录完全找不到匹配的t1数据,若有则抛出异常
完整实现代码
WITH MatchedRecords AS ( SELECT t2.[date] AS t2_date, t2.col1 AS t2_col1, t1.[date] AS matched_date, t1.col3 AS matched_col3, -- 按日期倒序排名,最近的匹配记录排第1位 ROW_NUMBER() OVER ( PARTITION BY t2.[date], t2.col1 ORDER BY t1.[date] DESC ) AS rn FROM t2 LEFT JOIN t1 ON t1.col3 = t2.col1 AND t1.[date] <= t2.[date] ) -- 输出最终匹配结果 SELECT matched_date AS [date], t2_col1 AS col1 FROM MatchedRecords WHERE rn = 1; -- 检查是否存在无法匹配的记录,若有则抛出异常 IF EXISTS ( SELECT 1 FROM t2 WHERE NOT EXISTS ( SELECT 1 FROM t1 WHERE t1.col3 = t2.col1 AND t1.[date] <= t2.[date] ) ) BEGIN THROW 50001, '存在无法匹配的记录,未找到符合条件的t1数据', 1; END
代码说明
- CTE关联与排名:通过
LEFT JOIN把t2的每条记录和所有符合col3匹配、日期不晚于t2.date的t1记录关联,再用ROW_NUMBER()窗口函数给每个t2记录的匹配结果按日期倒序排名,这样排名第1的就是我们需要的最优匹配(要么是完全匹配,要么是最近的更早日期记录) - 提取最优结果:从CTE中筛选出排名为1的记录,就是最终需要的输出
- 异常检查:通过
EXISTS判断是否有t2记录找不到任何符合条件的t1数据,若有则用THROW抛出自定义异常
为什么不用循环?
你之前尝试的循环方法不仅代码复杂,而且在数据量较大时性能会很差——循环是逐行处理,而窗口函数是基于集合的操作,SQL对这类操作的优化能力更强,执行效率更高,代码也更易维护。
针对你的示例数据,运行这段代码会精准输出你期望的结果:
14-05-2019 ttx会匹配到t1中更早的11-05-2019 ttx18-05-2020 abc会匹配到t1中最近的更早日期16-05-2020 abc19-05-2020 abc会直接匹配到t1中的同日期记录
内容的提问来源于stack exchange,提问作者Harsh




