SQL Server 2008 R2:匹配字符串
SQL Server 2008 R2: Matching strings
我有以下 table:
Table:
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
应该这样做 (demo)
SELECT DISTINCT CA.colstr
FROM str_matching s1
JOIN str_matching s2
ON s1.colstr <> s2.colstr
AND s2.colstr LIKE '%' + s1.colstr
CROSS APPLY (VALUES(s1.colstr),
(s2.colstr)) CA(colstr)
但是,如果 str_matching
有很多行,性能会很差。在字符串的反面添加索引可以显着改进 - 如下例所示。
CREATE TABLE str_matching
(
colstr varchar(200),
colstr_rev AS REVERSE(colstr)
);
CREATE INDEX ix_colstr_rev on str_matching(colstr_rev)
SELECT colstr = REVERSE(CA.colstr_rev)
FROM str_matching s1
JOIN str_matching s2
ON s1.colstr_rev <> s2.colstr_rev
AND s2.colstr_rev LIKE s1.colstr_rev + '%'
CROSS APPLY (VALUES(s1.colstr_rev),
(s2.colstr_rev)) CA(colstr_rev)
GROUP BY CA.colstr_rev
it can be match at any point.
要匹配任意点,请使用 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 +'%'
)
rextester 演示:http://rextester.com/ICIKJ2256
returns:
+-----------------+
| colstr |
+-----------------+
| A1010B |
| 5sXYZA1010B |
| B15K |
| AMZ103B15K |
| C101 |
| XC101 |
| FZ10009L |
| 502KMD1FZ10009L |
+-----------------+
鉴于 Martin Smith 的回答,我猜我误解了你在 'match at any point' 背后的意图,所以为了只匹配字符串的结尾你不会使用尾随 + '%'
你可以使用它。
;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
我有以下 table:
Table:
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
应该这样做 (demo)
SELECT DISTINCT CA.colstr
FROM str_matching s1
JOIN str_matching s2
ON s1.colstr <> s2.colstr
AND s2.colstr LIKE '%' + s1.colstr
CROSS APPLY (VALUES(s1.colstr),
(s2.colstr)) CA(colstr)
但是,如果 str_matching
有很多行,性能会很差。在字符串的反面添加索引可以显着改进 - 如下例所示。
CREATE TABLE str_matching
(
colstr varchar(200),
colstr_rev AS REVERSE(colstr)
);
CREATE INDEX ix_colstr_rev on str_matching(colstr_rev)
SELECT colstr = REVERSE(CA.colstr_rev)
FROM str_matching s1
JOIN str_matching s2
ON s1.colstr_rev <> s2.colstr_rev
AND s2.colstr_rev LIKE s1.colstr_rev + '%'
CROSS APPLY (VALUES(s1.colstr_rev),
(s2.colstr_rev)) CA(colstr_rev)
GROUP BY CA.colstr_rev
it can be match at any point.
要匹配任意点,请使用 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 +'%'
)
rextester 演示:http://rextester.com/ICIKJ2256
returns:
+-----------------+
| colstr |
+-----------------+
| A1010B |
| 5sXYZA1010B |
| B15K |
| AMZ103B15K |
| C101 |
| XC101 |
| FZ10009L |
| 502KMD1FZ10009L |
+-----------------+
鉴于 Martin Smith 的回答,我猜我误解了你在 'match at any point' 背后的意图,所以为了只匹配字符串的结尾你不会使用尾随 + '%'
你可以使用它。
;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