【问题标题】:lookup and replace part of a string for all cells in a column using text in cells for a separate table as the lookup criteria使用单独表格的单元格中的文本作为查找条件,查找和替换列中所有单元格的部分字符串
【发布时间】:2019-06-05 19:28:19
【问题描述】:

我正在使用 Sql Server 2014

我有两张桌子,每张都有两列。一个有名字和地址(表名是dbo.tgt_address),另一个有常见的街道缩写和对应的缩写我想把原来的缩写改成(表名是dbo.street_abreviations)。

我需要一个查询来将 tgt_address 表的 Address 列中的文本(该文本包含 Street_abbreviation 表的 common_used 列中的文本)更改为 Abbreviation 中的文本。

输出:

我知道这可能适用于个别行:

select replace(Address,'123 State St Chester PA 25374', '123 State ST Chester PA 25374')

但由于我在此处报告的表中有更多记录,我怎样才能创建一个更快的流程?我需要以某种方式合并 substring() 和 subselect 吗?我试图找到这方面的文档但失败了,所以我希望有人可以提供一些指导,至少让我开始,谢谢!

【问题讨论】:

  • 清除地址几乎不可能像您尝试做的那样。看看你的第一个例子,你有 ST 作为 st 的替代品。但是您在第一个地址中有两个字符串“st”的实例。您只需将其拆分为空格,然后评估每个元素以确定是否需要调整,最后再次重新组装片段。
  • 这是一个滑坡。您认为您已将 St for Street 之类的项目钉牢,但 St Louis 呢?特拉华州的 DE,但乔治亚州的德索托呢?不妨看看stackoverflow.com/questions/41249742/…
  • 正如肖恩所说,这不是一个人的任务。有些公司这样做可以赚很多钱。搜索地址标准化。如果您打算创建自己的地址标准化工具,则应首先考虑将地址分解为各个部分。站点编号、街道名称、街道名称前缀、街道名称后缀、zip、zip4、站点编号前缀/后缀(适用于 123 B Main St 等)。标准化具有广泛标准(其部分)但...的地址的非常复杂的主题。
  • 在美国有 3000 多个县,您可以找到各种复杂的本地地址。正如约翰所说,这是一个危险的滑坡。你在一些地址上取得了一些进展,然后更多的地址开始进入(假设成功),你开始看到各种愚蠢,你已经致力于你的地址标准化,所以你继续……呃!当心!祝你好运。
  • 样本数据最好使用DDL + DML。请edit您的问题包括它,您当前的尝试和您想要的结果。更多详情,read this.

标签: sql-server tsql database-design replace subquery


【解决方案1】:

地址是滑坡,但这可以帮助我相信:

初始数据:

DECLARE @tgt_address TABLE (ID INT IDENTITY(1,1),Name NVARCHAR(255),Address NVARCHAR(255));
INSERT INTO @tgt_address(Name,Address)VALUES
      ('John','123 State St Chester PA 25374')
     ,('Steve','798 Main Avn New York NY 21314')
     ,('Martha','981 West Ln Wilmington De 23142')
     ,('Mary','124 Main Street #2 Austin Tx 21432')
     ,('Timothy','25 Lark Thwy Maiami FL 12342')
;
DECLARE @Street_abbreviation TABLE (Commonly_used NVARCHAR(255),Abbreviation NVARCHAR(255));
INSERT INTO @Street_abbreviation(Commonly_used,Abbreviation)VALUES
     ('St','ST')
    ,('Avn','AVE')
    ,('Ln','LN')
    ,('#','APT')
    ,('Thwy','THROUGHWAY')
;

不是最好的,但很简单的代码:

SELECT t.Name,t.Address
    ,REPLACE(REPLACE(t.Address,'#','# '),' ' + a.Commonly_used + ' ',' ' + a.Abbreviation + ' ') AS [Result]
FROM @tgt_address t
INNER JOIN @Street_abbreviation a ON REPLACE(t.Address,'#','# ') LIKE '%[ ]' + a.Commonly_used + '[ ]%'
;

更智能的代码:

SELECT r.Name,r.Address,r.Result
FROM (
    SELECT t.Name,t.Address
        ,REPLACE(REPLACE(t.Address,'#','# '),' ' + a.Commonly_used + ' ',' ' + a.Abbreviation + ' ') AS [Result]
        ,ROW_NUMBER()OVER(PARTITION BY t.Name,t.Address 
                        ORDER BY CASE WHEN REPLACE(t.Address,'#','# ') LIKE '%[ ]' + a.Commonly_used + '[ ]%' THEN 0 ELSE 1 END) AS [rn]
    FROM @tgt_address t
    CROSS JOIN @Street_abbreviation a
) r
WHERE r.rn = 1
;

公寓很棘手,因为 # 周围没有空间

【讨论】:

  • 感谢 VItaly,我认为这将帮助我实现临时目标
猜你喜欢
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
  • 2023-01-31
  • 2014-12-21
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
  • 2011-07-12
相关资源
最近更新 更多