You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用SQL实现t1与t2匹配及无匹配时的前置日期匹配逻辑?

我来帮你搞定这个SQL匹配的问题,其实不用写复杂的循环,用窗口函数就能高效解决,而且代码更简洁易维护。下面是具体的实现思路和完整代码:

核心思路拆解

我们的目标是为t2的每条记录找到符合要求的t1数据,分三个核心步骤:

  1. 先关联t1和t2,筛选出完全匹配(t2.date = t1.date 且 t2.col1 = t1.col3)的记录
  2. 对没有完全匹配的t2记录,找到t1中日期早于t2.date且col3等于t2.col1的所有记录,取其中最近的日期那条
  3. 最后检查是否存在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
代码说明
  1. CTE关联与排名:通过LEFT JOIN把t2的每条记录和所有符合col3匹配、日期不晚于t2.date的t1记录关联,再用ROW_NUMBER()窗口函数给每个t2记录的匹配结果按日期倒序排名,这样排名第1的就是我们需要的最优匹配(要么是完全匹配,要么是最近的更早日期记录)
  2. 提取最优结果:从CTE中筛选出排名为1的记录,就是最终需要的输出
  3. 异常检查:通过EXISTS判断是否有t2记录找不到任何符合条件的t1数据,若有则用THROW抛出自定义异常
为什么不用循环?

你之前尝试的循环方法不仅代码复杂,而且在数据量较大时性能会很差——循环是逐行处理,而窗口函数是基于集合的操作,SQL对这类操作的优化能力更强,执行效率更高,代码也更易维护。

针对你的示例数据,运行这段代码会精准输出你期望的结果:

  • 14-05-2019 ttx会匹配到t1中更早的11-05-2019 ttx
  • 18-05-2020 abc会匹配到t1中最近的更早日期16-05-2020 abc
  • 19-05-2020 abc会直接匹配到t1中的同日期记录

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

火山引擎 最新活动