2017-10-10 6 views
1

나는 다음과 같은 테이블이 :SQL 서버 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') 
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
  • 1 문자열의 끝에서 일치되는 2 문자열

      , 그래서 기록을 표시합니다.

      참고 : 문자열의 길이는 고정되어 있지 않으며 어느 시점이든 일치 할 수 있습니다.

      예상 결과 :

      colstr    
      -------------------- 
      5sXYZA1010B   
      A1010B    
      AMZ103B15K   
      B15K     
      XC101    
      C101     
      502KMD1FZ10009L  
      FZ10009L   
      
    +0

    문자열의 끝을 비교하는 [가장 좋은 방법의 사용 가능한 복제, RIGHT, LIKE 또는 기타를 사용합니까?] (https://stackoverflow.com/questions/7394276/best-way-to-compare-the-end-of-a-string-use-right-like-or-other) –

    +2

    @TabAlleman [다음은 데이터입니다 explorer query] (https://data.stackexchange.com/stackoverflow/query/738866/answers-to-duplicate-questions-by-user)를 사용하면 사용자 ID가 중복 표시된 질문에 대한 모든 대답을 찾을 수 있습니다. 사용자 ID 1507566으로 시작할 수 있습니다. – SqlZim

    답변

    2

    이것은 str_matching 가난 것이다 많은 행 성능을 가지고 그러나 경우

    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) 
    

    (demo)

    을 수행해야합니다. 문자열의 반대쪽에 색인을 추가하면 아래 예에서와 같이 내용이 크게 향상 될 수 있습니다.

    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 
    
    +0

    'cross apply()'에서'union all'이 아닌'union '을 사용하고 있기 때문에'distinct'와'union' 둘 다 필요합니까? – SqlZim

    +0

    @SqlZim 안쪽에'UNION'은 꼭 필요하지 않습니다.'s1.colstr <> s2.colstr'은 절대로 같지 않을 것임을 의미합니다. –

    +0

    @MartinSmith로 변경됩니다. 41k 레코드를 실행하는 데 15 분 이상 걸립니다. – MAK

    1

    그것은 어떤 점에서 일치 될 수 있습니다. http://rextester.com/ICIKJ2256

    반환 : 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 데모를 추가, 여러 일치하는

    :

    각 측면에 와일드 카드 (%)와 like를 사용, 어느 시점을 일치 시키려면

    +-----------------+ 
    |  colstr  | 
    +-----------------+ 
    | A1010B   | 
    | 5sXYZA1010B  | 
    | B15K   | 
    | AMZ103B15K  | 
    | C101   | 
    | XC101   | 
    | FZ10009L  | 
    | 502KMD1FZ10009L | 
    +-----------------+ 
    

    당신이 당신이 할 수있는 후행 + '%'

    1

    를 사용하지 않을 문자열의 끝과 일치하는, 그래서 내가, 내가 '어떤 점에서 일치'뒤에 의도를 오해 같은데요 마틴 스미스의 대답을 감안할 때 그걸 써.

    ;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