从右一次从字符串中删除一个字符,直到找到匹配项

时间:2017-03-23 02:21:18

标签: sql sql-server string

我有两个用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                       |
+---------------+---------------+-----------------------------------+

2 个答案:

答案 0 :(得分: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;

我不想说这是有效的,但它应该做你想要的。并且,它在一个小数据集上很好。

答案 1 :(得分: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