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开始。