SQL Server 2008 R2:匹配字符串
我有下表: 表:SQL Server 2008 R2:匹配字符串,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我有下表: 表: CREATE TABLE str_matching ( colstr varchar(200) ); 插入数据: INSERT INTO str_matching VALUES('5sXYZA1010B') INSERT INTO str_matching VALUES('A1010B') INSERT INTO str_matching VALUES('AMZ103B15K') INSERT INTO str_matching VALUES('B15K') INSE
CREATE TABLE str_matching
(
colstr varchar(200)
);
插入数据:
INSERT INTO str_matching VALUES('5sXYZA1010B')
INSERT INTO str_matching VALUES('A1010B')
INSERT INTO str_matching VALUES('AMZ103B15K')
INSERT INTO str_matching VALUES('B15K')
INSERT INTO str_matching VALUES('XC101')
INSERT INTO str_matching VALUES('C101')
INSERT INTO str_matching VALUES('502KMD1FZ10009L')
INSERT INTO str_matching VALUES('FZ10009L')
INSERT INTO str_matching VALUES('A9L')
INSERT INTO str_matching VALUES('XZ049L')
INSERT INTO str_matching VALUES('LM101')
预期输出:我只想显示那些有重复条目的记录,如果一个字符串匹配任何字符串的最后一部分,那么我认为是重复的
例如:我有两个字符串
5sXYZA1010B
A1010B
colstr
--------------------
5sXYZA1010B
A1010B
AMZ103B15K
B15K
XC101
C101
502KMD1FZ10009L
FZ10009L
这样就可以了()
这样就可以了()
它可以在任何点匹配
要匹配任何点,请在每侧使用带有通配符(%
)的like
:
对于多个匹配项,添加distinct
select l.colstr
from str_matching l
inner join str_matching r
on l.colstr<>r.colstr
and (l.colstr like '%' + r.colstr +'%'
or r.colstr like '%' + l.colstr +'%'
)
根据Martin Smith的回答,我猜我误解了您在“任意点匹配”后面的意图,因此为了只匹配字符串的结尾,您不会使用尾随的
+'%'
它可以在任何点匹配
要匹配任何点,请在每侧使用带有通配符(%
)的like
:
对于多个匹配项,添加distinct
select l.colstr
from str_matching l
inner join str_matching r
on l.colstr<>r.colstr
and (l.colstr like '%' + r.colstr +'%'
or r.colstr like '%' + l.colstr +'%'
)
根据Martin Smith的回答,我猜我误解了您在“任意点匹配”后面的意图,因此为了只匹配字符串的结尾,您不会使用尾随的
+'%'
,您可以使用它
;WITH CTE AS (
select *,RN = ROW_NUMBER() OVER (ORDER BY LEN(colstr)) from str_matching
)
,CTE2 AS (
SELECT T1.colstr colstr1 ,X.colstr colstr2 FROM CTE T1
CROSS APPLY (SELECT * FROM CTE T2 WHERE T2.RN > T1.RN AND RIGHT(T2.colstr, LEN(T1.colstr)) = T1.colstr) AS X
)
SELECT colstr1 FROM CTE2
UNION ALL
SELECT colstr2 FROM CTE2
结果:
5sXYZA1010B
A1010B
AMZ103B15K
B15K
XC101
C101
502KMD1FZ10009L
FZ10009L
你可以用它
;WITH CTE AS (
select *,RN = ROW_NUMBER() OVER (ORDER BY LEN(colstr)) from str_matching
)
,CTE2 AS (
SELECT T1.colstr colstr1 ,X.colstr colstr2 FROM CTE T1
CROSS APPLY (SELECT * FROM CTE T2 WHERE T2.RN > T1.RN AND RIGHT(T2.colstr, LEN(T1.colstr)) = T1.colstr) AS X
)
SELECT colstr1 FROM CTE2
UNION ALL
SELECT colstr2 FROM CTE2
结果:
5sXYZA1010B
A1010B
AMZ103B15K
B15K
XC101
C101
502KMD1FZ10009L
FZ10009L
由于在
cross apply()
中使用union
而不是union all
,您是否同时需要distinct
和union
呢?@SqlZim我当然不需要内部union
,s1.colstr s2.colstr
意味着它们永远不会相同。意志change@MartinSmith,执行41k条记录需要15分钟以上的时间。@MAK-我一点也不奇怪。这将需要对1681000000个交叉连接的行进行比较。要优化它,您需要存储字符串的反向副本并为该列编制索引,然后重写查询以使用该列和尾随通配符。@MAK-添加了一个例子,您是否需要使用distinct
和union
,因为您在交叉中使用的是union
而不是union all
apply()。意志change@MartinSmith,执行41k条记录需要15分钟以上的时间。@MAK-我一点也不奇怪。这将需要对1681000000个交叉连接的行进行比较。要优化它,您需要存储字符串的反向副本并为该列编制索引,然后重写查询以使用该列和尾随通配符。@MAK-添加了一个可能重复的@TabAlleman的示例,以便您可以找到标有“用户ID重复”的问题的所有答案。您可以从用户id 1507566开始。可能是@TabAlleman的重复项,因此您可以找到标有“用户id重复”的问题的所有答案。您可以从用户id 1507566开始。