【问题标题】:Specific string matching特定字符串匹配
【发布时间】:2019-08-01 03:42:31
【问题描述】:

我在 SQL Server 2012 中工作。在我的表中,有一个名为St_Num 的列,它的数据是这样的:

St_Num                 status
------------------------------
128 TIMBER RUN DR      EXP
128 TIMBER RUN DRIVE   EXP

现在我们可以注意到上面的数据存在拼写变化。我想做的是,如果这种情况下的数字 128 和 St_Num 列中的前 3 个字母相同,那么这两行应该被认为是相同的,输出应该是:

St_Num                status
-----------------------------
128 TIMBER RUN DR     EXP

我对此进行了一些搜索,发现 left 或 substring 函数在这里很方便,但我不知道如何在这里使用它们来获得我需要的东西,即使它们能解决我的问题也不知道。关于如何获得所需输出的任何帮助都会很棒。

【问题讨论】:

标签: sql sql-server string substring string-matching


【解决方案1】:

这可以通过使用子查询来完成,就像消除表中的重复项一样:

SELECT Str_Num, status
FROM <your_table> a
WHERE NOT EXISTS (SELECT 1
FROM <your_table> b
WHERE SUBSTRING(b.Str_Num, 1, 7) = SUBSTRING(a.Str_Num, 1, 7));

这只有在保证数字长度为 3 个字符的情况下才有效,或者如果您不介意在数字较少字符的情况下占用更多字符。

【讨论】:

    【解决方案2】:

    这将只输出匹配的第一行:

    with cte as (
      select *,
      row_number() over (order by (select null)) rn
      from tablename
    )
    select St_Num, status from cte t
    where not exists (
      select 1 from cte
      where 
        left(St_Num, 7) = left(t.St_Num, 7)
        and
        rn < t.rn
    )
    

    demo

    【讨论】:

    • 如果存在“128 TIMBER HILL”或其他类似名称,或者存在诸如“128 TMBER RUN DR”之类的拼写错误,则会失败
    • 如果本例中的数字 128 和 St_Num 列中的前 3 个字母相同,则这两行应视为相同这是要求。
    • @zain ul abidin:如果这个要求只用于返回数据,还可以,但是如果你在UPDATE语句中使用它来标准化地址会导致灾难。
    • @forpas 我需要的是,当第一次查询通过 123 TIMBER RUN DR 时,然后在 St_Num 列中,它再次通过字段 123 TIMBER RUN DRIVE 然后它应该检查如果有 123 个 TIM 匹配,则不显示此记录,而仅显示第一个。
    • @zainulabidin 是否有像 id(整数自动增量)这样的列可以用作行的顺序?
    【解决方案3】:

    您可以使用statussubstring(St_Num,1,3) 分组

    with t(St_Num, status) as
    (
     select '128 TIMBER RUN DR'   ,'EXP' union all
     select '128 TIMBER RUN DRIVE','EXP'   
    ) 
    select min(St_Num) as St_Num, status
      from t    
     group by status, substring(St_Num,1,3);
    
    St_Num              status
    -----------------   ------
    128 TIMBER RUN DR   EXP
    

    【讨论】:

      【解决方案4】:

      我不太赞同你的匹配逻辑。 . .但这不是你的问题。最大的问题是字符串前面的数字有多长。因此,您可以使用以下方法获得最短的地址:

      select distinct t.*
      from t
      where not exists (select 1
                        from t t2
                        where left(t2.st_num, patindex('%[a-zA-Z]%') + 2, t.st_num) = left(t.st_num, patindex('%[a-zA-Z]%', t.st_num) + 2) and
                              len(t.St_Num) < len(t2.St_Num)
                       );
      

      【讨论】:

        【解决方案5】:

        我仍然觉得您的标准不足以匹配相同的地址,但这可能会有所帮助,因为它还考虑了数字的长度:

        WITH ParsedAddresses(st_num, exp, number)
        AS
        (
            SELECT st_num,
            exp,
            number = ROW_NUMBER() OVER(PARTITION BY LEFT(st_num, CHARINDEX(' ', st_num) + 3) ORDER BY LEN(st_num))
            FROM <table_name>
        )
        SELECT st_num, exp FROM ParsedAddresses
        WHERE number = 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多