如何在CASE语句中匹配列并忽略字符串中的单个指定字符?
关于CASE语句中忽略字符串第三个字符匹配两表列的问题
我尝试在CASE语句中匹配两个表的列,同时忽略字符串中的第三个字符。
示例数据
IF OBJECT_ID('tempdb..#t1') IS NOT NULL DROP TABLE #t1 IF OBJECT_ID('tempdb..#t2') IS NOT NULL DROP TABLE #t2 CREATE TABLE #t1 ( courseid VARCHAR(10) ) INSERT INTO #t1( courseid ) VALUES ('00.123456') ,('01.234567') ,('02.345678') CREATE TABLE #t2 ( courseid VARCHAR(10) ) INSERT INTO #t2( courseid ) VALUES ('00.923456') ,('01.834567') ,('02.745678')
请问以下匹配方式是否可靠?(第三个SELECT语句仅作参考,实际代码可运行,我想了解使用LEFT/RIGHT是否可靠,或有无通配符等更优方式)
测试用SQL代码
SELECT t1.courseid ,LEFT(t1.courseid,2)+RIGHT(t1.courseid,5) AS T1_CourseID FROM #t1 AS t1 SELECT t2.courseid ,LEFT(t2.courseid,2)+RIGHT(t2.courseid,5) AS T2_CourseID FROM #t2 AS t2 SELECT CASE WHEN EXISTS (SELECT t1.CourseID FROM #T1 AS t1 WHERE LEFT(t1.courseid,2)+RIGHT(t1.courseid,5)= LEFT(t2.courseid,2)+RIGHT(t2.courseid,5)) THEN 1 ELSE 0 END IsMatchedCourse FROM #t1 AS T1
查询结果
所有行的IsMatchedCourse值均为1,说明匹配逻辑生效。
1. LEFT/RIGHT组合的可靠性
在你当前的固定格式场景下,LEFT(t1.courseid,2)+RIGHT(t1.courseid,5)的写法是可靠的——因为所有courseid长度固定为8位,需要忽略的恰好是第3位字符。
但这种写法有明显局限性:
- 若
courseid长度不固定,RIGHT函数会返回不足5位的字符,导致拼接结果不符合预期; - 若需要忽略的位置不是固定第3位,该写法直接失效。
2. 更优实现方式
方式一:STUFF函数(推荐,直观灵活)
STUFF函数可直接删除指定位置的字符,无需依赖固定长度,语法更清晰:
SELECT CASE WHEN EXISTS (SELECT 1 FROM #T1 AS t1 WHERE STUFF(t1.courseid, 3, 1, '') = STUFF(t2.courseid, 3, 1, '')) THEN 1 ELSE 0 END IsMatchedCourse FROM #t1 AS T2
STUFF(t1.courseid, 3, 1, '')意为从courseid第3位开始删除1个字符,直接忽略目标位置,适配任意长度的字符串(只要长度≥3)。
方式二:SUBSTRING组合
和LEFT/RIGHT逻辑类似,但通过动态长度计算适配不同格式:
SELECT CASE WHEN EXISTS (SELECT 1 FROM #T1 AS t1 WHERE SUBSTRING(t1.courseid,1,2) + SUBSTRING(t1.courseid,4,LEN(t1.courseid)-3) = SUBSTRING(t2.courseid,1,2) + SUBSTRING(t2.courseid,4,LEN(t2.courseid)-3)) THEN 1 ELSE 0 END IsMatchedCourse FROM #t1 AS T2
通过LEN(t1.courseid)-3动态计算右侧截取长度,避免固定位数的限制。
方式三:通配符LIKE匹配
用单个字符通配符_忽略第3位,但性能通常不如前两种写法(易触发全表扫描):
SELECT CASE WHEN EXISTS (SELECT 1 FROM #T1 AS t1 WHERE t1.courseid LIKE LEFT(t2.courseid,2) + '_' + RIGHT(t2.courseid,5)) THEN 1 ELSE 0 END IsMatchedCourse FROM #t1 AS T2
3. 性能优化建议
若数据量较大,建议创建持久化计算列并添加索引,大幅提升匹配效率:
ALTER TABLE #t1 ADD courseid_ignore3 AS STUFF(courseid,3,1,'') PERSISTED CREATE INDEX IX_t1_courseid_ignore3 ON #t1(courseid_ignore3) ALTER TABLE #t2 ADD courseid_ignore3 AS STUFF(courseid,3,1,'') PERSISTED CREATE INDEX IX_t2_courseid_ignore3 ON #t2(courseid_ignore3)
后续查询直接用计算列匹配即可。
内容的提问来源于stack exchange,提问作者JM1
相关产品推荐
相关产品推荐

