Microsoft SQL Server多表Join重复匹配问题求助
解决SQL Server中链接与名称关联的重复匹配问题
你当前的关联逻辑仅通过截取链接右侧与名称长度一致的内容进行匹配,会导致一个链接匹配多个名称的重复问题——比如/http://bla-bla/Test+Link+For+Test替换空格后,既匹配Test Link For Test,又匹配其后缀Link For Test,从而产生重复行。以下两种方法可以解决这个问题:
方法1:保留每个链接的最长匹配项
利用窗口函数ROW_NUMBER(),给每个链接的所有匹配项按名称长度倒序编号,仅保留编号为1的最长匹配结果:
CREATE TABLE #Test1 ( link nvarchar(max) ) CREATE TABLE #Test2 ( Name nvarchar(max), ) INSERT INTO #Test1 VALUES ('/http://bla-bla/Link+For+Test'), ('/http://bla-bla/Test+Link+For+Test'), ('/http://bla-bla/Test+Link+For+Test+Second'), ('/bla-bla%Link+For+Edited+Test'), ('/bla-bla%2fFor+Test+Edited') INSERT INTO #Test2 VALUES ('Link For Test') ,('Test Link For Test') ,('Link For Edited Test') ,('For Test Edited') WITH MatchedData AS ( SELECT RIGHT(REPLACE(t1.link, '+', ' '), LEN(t2.[Name])) AS NameFromLink, t2.name, t1.link, ROW_NUMBER() OVER (PARTITION BY t1.link ORDER BY LEN(t2.[Name]) DESC) AS rn FROM #Test1 t1 INNER JOIN #Test2 t2 ON RIGHT(REPLACE(t1.link, '+', ' '), LEN(t2.[Name])) = t2.[Name] ) SELECT NameFromLink, name, link FROM MatchedData WHERE rn = 1; DROP TABLE #Test1 DROP TABLE #Test2
核心逻辑:通过PARTITION BY t1.link按链接分组,ORDER BY LEN(t2.[Name]) DESC让最长的名称排在前面,rn=1筛选出每个链接的最优匹配项。
方法2:优化关联条件,匹配完整末尾段
通过添加额外条件,确保匹配的名称是链接中独立的末尾片段(前面是分隔符/或空格,或链接本身就是该名称),从根源上避免后缀匹配:
CREATE TABLE #Test1 ( link nvarchar(max) ) CREATE TABLE #Test2 ( Name nvarchar(max), ) INSERT INTO #Test1 VALUES ('/http://bla-bla/Link+For+Test'), ('/http://bla-bla/Test+Link+For+Test'), ('/http://bla-bla/Test+Link+For+Test+Second'), ('/bla-bla%Link+For+Edited+Test'), ('/bla-bla%2fFor+Test+Edited') INSERT INTO #Test2 VALUES ('Link For Test') ,('Test Link For Test') ,('Link For Edited Test') ,('For Test Edited') SELECT RIGHT(REPLACE(t1.link, '+', ' '), LEN(t2.[Name])) AS NameFromLink, t2.name, t1.link FROM #Test1 t1 INNER JOIN #Test2 t2 ON RIGHT(REPLACE(t1.link, '+', ' '), LEN(t2.[Name])) = t2.[Name] AND ( -- 链接本身长度等于名称长度 LEN(REPLACE(t1.link, '+', ' ')) = LEN(t2.[Name]) OR -- 匹配部分的前一个字符是分隔符 SUBSTRING(REPLACE(t1.link, '+', ' '), LEN(REPLACE(t1.link, '+', ' ')) - LEN(t2.[Name]), 1) IN ('/', ' ') ) DROP TABLE #Test1 DROP TABLE #Test2
核心逻辑:通过检查匹配片段的前置字符是否为分隔符,确保匹配的是完整的名称段,而非长名称的后缀部分。
内容的提问来源于stack exchange,提问作者Ekaterina Chistyakova
相关产品推荐
相关产品推荐

