2017-03-23 3 views
1

ID가있는 임시 테이블이 두 개 있습니다.문자열에서 한 번에 한 문자 씩 오른쪽에서 일치 항목이 발견 될 때까지 제거합니다.

#Master 테이블은 한 시스템에서 가져오고 #Extended 테이블은 사람들이 Id에 문자를 추가 한 다른 시스템의 테이블입니다.

지금 문제는 SELECT 쿼리를 작성하여 일치하는 항목이 있는지 확인하거나 일치하는 항목이있을 때까지 한 번에 하나의 문자를 제거하지 않을 것인지 확인하는 것입니다. 아래에서 볼 수 있듯이 정확히 일치하지 않을 경우 가능한 값 중 하나 (1-12L7QABC는 1-12L7QO 또는 1-12L7QM을 반환 할 수 있음)를 반환하고자하는 경우가 있습니다.

CREATE TABLE #Master(Id nvarchar(15), ClientName nvarchar(35)); 
INSERT INTO #Master 
VALUES('1-12L7QO', 'John Citizen'), 
     ('1-12L7QM', 'Steve Smith'), 
     ('1-10YL', 'Sarah Connor'), 
     ('1-2CN9WN', 'Cathy Rodgers'); 

CREATE TABLE #Extended(ExtId varchar(15)); 
INSERT INTO #Extended 
VALUES('1-12L7QO`'), 
     ('1-12L7QABC'), 
     ('1-10YL'), 
     ('1-12L7QMTest'); 

예상 출력은 다음과 같습니다

+---------------+---------------+-----------------------------------+ 
| Id   | BaseId  | Name        | 
+---------------+---------------+-----------------------------------+ 
| 1-12L7QO`  | 1-12L7QO  | John Citizen      | 
| 1-12L7QABC | 1-12L7QO  | John Citizen      | 
| 1-10YL  | 1-10YL  | Sarah Connor      | 
| 1-12L7QMTest | 1-12L7QM  | Steve Smith      | 
+---------------+---------------+-----------------------------------+ 
+1

힌트 ... Master.ID + '%'또는 일부 변형과 같이 확장 .ID를 사용하십시오. 각 CHARINDEX에 대한 루핑은 작업 기반으로 설정되지 않으므로 퍼지 일치 및 FULL TEXT 인덱싱으로보다 잘 처리됩니다. – scsimon

답변

1

한 가지 방법은 가능한 모든 문자열을 만드는 것입니다 다음 경기 수행

with m as (
     select m.id, m.ClientName 
     from #Master m 
     union all 
     select left(m.id, len(m.Id) - 1), m.ClientName 
     from m 
     where m.Id <> '' 
    ) 
select e.ExtId, m.Id, m.ClientName 
from #Extended e outer apply 
    (select top 1 m.* 
     from m 
     where e.ExtId like m.id + '%' 
     order by len(m.id) desc 
    ) m; 

나는이 것을 주장하지 않으을 효율적이지만 원하는 것을해야합니다. 작은 데이터 세트에서는 문제가 없습니다.

+0

매우 우아한 솔루션이며 내가 작업하고있는 데이터 세트가 야간에 ETL의 일부로 실행되는 것은 아닙니다.이 경우 성능은 문제가되지 않습니다. 내가 궁금해하는 유일한 점은 1-12L7QABC가 1-12L7Q 대신 스티브 스미스의 전체 ID 1-12L7QM을 표시 할 수 있다는 것입니다. – sams

+0

@ 샘. . . 일치하는 "full"id를 원하면 재귀 적 CTE에 넣을 수 있습니다. –

1

시험해보기 : 원하는대로 정확하게 작업 해보십시오.

  CREATE TABLE #MasterMatch(RowId INT,Master_Id nvarchar(15), ExtId varchar(15),ClientName nvarchar(35),Rank_Got Decimal(20,4)); 
      Select row_number() over(order by ExtId desc) as RowId,ExtId into #Extended1 from #Extended 
      Declare @Id_Len INT 
      Declare @Rec_Cnt INT 
      Declare @ExtId varchar(15) 
      Declare @ExtId1 varchar(15) 
      SET @Rec_Cnt = (SELECT Count(1) FROM #Extended1) 
      Print @Rec_Cnt 
      WHILE(@Rec_Cnt > 0) 
      BEGIN 
      SELECT @ExtId = ExtId from #Extended1 where Rowid = @Rec_Cnt 
      SET @ExtId1 = @ExtId 
      SELECT @Id_Len = Len(@ExtId) 
      WHILE (@Id_Len > 2) 
      BEGIN 
      IF EXISTS (SELECT 1 FROM #Master WHERE Id = @ExtId) 
      BEGIN 
      INSERT INTO #MasterMatch 
      SELECT @Rec_Cnt,Id As Master_Id,@ExtId1 AS ExtId,ClientName,(CONVERT(DECIMAL(20,4),@Id_Len)/CONVERT(DECIMAL(20,4),@Rec_Cnt)) As Rank_Got FROM #Master WHERE Id = @ExtId 
      SET @Id_Len = (@Id_Len - 1) 
      SET @ExtId = SUBSTRING(@ExtId,0,@Id_Len) 
      END 
      ELSE 
      BEGIN 
      INSERT INTO #MasterMatch 
      SELECT @Rec_Cnt,Id As Master_Id,@ExtId1 AS ExtId,ClientName,(CONVERT(DECIMAL(20,4),@Id_Len)/CONVERT(DECIMAL(20,4),@Rec_Cnt)) As Rank_Got FROM #Master WHERE Id like @ExtId + '%' 
      SET @Id_Len = (@Id_Len - 1) 
      SET @ExtId = SUBSTRING(@ExtId,0,@Id_Len) 
      END 
      END 
      SET @Rec_Cnt = (@Rec_Cnt - 1) 
      END 

      Select Id,Base_id,Name 
      FROM (
      Select ROW_NUMBER() OVER(Partition by ExtId ORDER BY Master_Id) As SnId,ExtId As Id,Master_Id As Base_id,ClientName As Name FROM #MasterMatch a INNER JOIN (select RowId,MAX(Rank_Got) As Rank_Got from #MasterMatch GROUP BY RowId) b on a.RowId = b.RowId and a.Rank_Got = b.Rank_Got 
      ) one 
      WHERE one.SnId = 1 
+0

안타깝게도 1-12L7QO'에 대한 해결책으로 John Citizen 대신 Steve Smith가 답장을 보내 주셔서 감사합니다. – sams

관련 문제