【问题标题】:Getting 5 digit Zip Code from string Data从字符串数据中获取 5 位邮政编码
【发布时间】:2019-11-19 17:24:39
【问题描述】:

我有一个包含 City、State Zip 和 Country 的字符串。我已经能够将城市和州从字符串中提取到单独的列中,但是在提取邮政编码时遇到了问题。这是我从中提取的数据的示例。

哥伦布,俄亥俄州 43219,美国

我试过的代码是这样的

Replace(LTRIM(RTRIM(LEFT(C.[BILLING_CITYSTATEZIP], CHARINDEX(',', C.[BILLING_CITYSTATEZIP])))),',','')as City,

   left(LTRIM(RTRIM(SUBSTRING(C.[BILLING_CITYSTATEZIP], CHARINDEX(',', C.[BILLING_CITYSTATEZIP])+1, LEN(C.[BILLING_CITYSTATEZIP])-(CHARINDEX('', C.[BILLING_CITYSTATEZIP])-1)))),2)as State,

   dbo.udf_GetNumeric(Right(LTRIM(RTRIM(Substring(C.[BILLING_CITYSTATEZIP], CHARINDEX(',', C.[BILLING_CITYSTATEZIP])+1, LEN(C.[BILLING_CITYSTATEZIP])-(CHARINDEX('',C.[BILLING_CITYSTATEZIP]-1)))),2))as Zip,

我包含了用于提取城市和州的代码,因为我将邮政编码的行从州行镜像,但我不断收到以下错误。我无法弄清楚我在哪里错过了 ltrim 的论点。任何的建议都受欢迎。

消息 174,级别 15,状态 1,第 36 行 ltrim 函数需要 1 个参数。 消息 102,第 15 级,状态 1,第 52 行 ',' 附近的语法不正确。

【问题讨论】:

  • 试试dbo.udf_GetNumeric(Right(LTRIM(RTRIM(Substring(C.[BILLING_CITYSTATEZIP], CHARINDEX(',', C.[BILLING_CITYSTATEZIP])+1, LEN(C.[BILLING_CITYSTATEZIP])-(CHARINDEX('', C.[BILLING_CITYSTATEZIP])-1)))),2))as Zip,
  • 注意 udf_getnumeric 函数,因为某些州的邮政编码中有前导 0。
  • 这只是一个语法错误。你在最后缺少一个右括号。但希望您能够修复设计,而不是将所有这些数据存储在同一个元组中。你发现它很痛苦,它也违反了 1NF。
  • 感谢您的提醒!我会记住这一点的。
  • @NewCoder04 1NF= 第一范式,您应该对存储在数据库中的所有数据执行此操作。有这样的字符串通常被认为是糟糕的设计,然后你需要将它“转换”为你可以使用的东西......

标签: sql-server tsql substring


【解决方案1】:

你可以这样使用:

select case when patindex('% [0-9][0-9][0-9][0-9][0-9],%', c) > 0 then
SUBSTRING(c, patindex('% [0-9][0-9][0-9][0-9][0-9],%', c) + 1, 5)
else '' end as zipCode
from
(
select 'Columbus,OH 43219, United States' as c
union all
select 'Chicago,IL 60626, United States' as c
) c

【讨论】:

  • 快速提问。如果我要移动的记录超过 5000 条,是否需要为每个不同的地址字符串执行单独的 Union all 语句?如果是,有没有办法可以在 from (select) 中指定一种字符串?
  • 这只是一个例子。只需将此部分case when patindex('% [0-9][0-9][0-9][0-9][0-9],%', c) > 0 then SUBSTRING(c, patindex('% [0-9][0-9][0-9][0-9][0-9],%', c) + 1, 5) else '' end as zipCode 用作您自己的SELECT 的一部分。
【解决方案2】:

这是一种使用子字符串的方法:

DECLARE @address NVARCHAR(500) = 'Columbus,OH 43219, United States'

SELECT SUBSTRING(SUBSTRING(SUBSTRING(@address, CHARINDEX(',',@address) + 1, LEN(@address)),0,CHARINDEX(',',SUBSTRING(@address, CHARINDEX(',',@address) + 1, LEN(@address)))),
    CHARINDEX(' ',SUBSTRING(SUBSTRING(@address, CHARINDEX(',',@address) + 1, LEN(@address)),0,CHARINDEX(',',SUBSTRING(@address, CHARINDEX(',',@address) + 1, LEN(@address))))) + 1,LEN(@address))

【讨论】:

    【解决方案3】:

    对于“城市”,你有埋在那里

    - (CHARINDEX('', C.[BILLING_CITYSTATEZIP])-1)
    

    对于“Zip”,在同一个位置

     - (CHARINDEX('', C.[BILLING_CITYSTATEZIP]-1))
    

    请注意,右括号是不同的。看起来你需要将这两个中的一个移到 -1 的“之前”。

    【讨论】:

    • ...这就是您的代码示例似乎有问题的地方。可能有更好的方法来写这个; SQL 在解析和处理字符串时非常糟糕,因为这不是它的本意。
    【解决方案4】:

    在处理复杂的字符串表达式时,APPLY 是你最好的朋友。您可以使用它来使您的代码更加干燥(D而不是R重复Y我们自己)。这使得代码更干净,更容易调试。

    DECLARE @BILLING_CITYSTATEZIP VARCHAR(200) = ' Columbus ,OH 43219, United States ';
    
    SELECT
      City    = SUBSTRING(f.String, a.Head,  a.Pos-1),
      [State] = SUBSTRING(f.String, a.Pos+1, b.Pos-a.Pos-1), 
      Zip     = SUBSTRING(f.String, b.Pos+1, c.Pos-b.Pos-1),
      Country = SUBSTRING(f.String, c.Pos+1, 200) -- BONUS
    FROM        (VALUES(RTRIM(LTRIM(REPLACE(REPLACE( -- All trimming (outer & inner) in 1 spot
                 @BILLING_CITYSTATEZIP,', ',','),' ,',','))))) AS f(String)
    CROSS APPLY (VALUES(CHARINDEX(',',f.String),1))            AS a(Pos,Head)
    CROSS APPLY (VALUES(CHARINDEX(' ',f.String,a.Pos+1)))      AS b(Pos)
    CROSS APPLY (VALUES(CHARINDEX(',',f.String,b.Pos+1)))      AS c(Pos);
    

    返回:

    City        State    Zip     Country
    ----------- -------- ------- -----------------
    Columbus    OH       43219   United States
    

    相对于一个表格,它看起来像这样:

    DECLARE @table TABLE (SomeId INT IDENTITY, BILLING_CITYSTATEZIP VARCHAR(200));
    INSERT  @table VALUES ('Columbus,OH 43219, United States'),('Chicago ,IL 60625, United States')
    
    SELECT t.SomeId, f.City, f.[State], f.[Zip], f.Country 
    FROM   @table AS t
    CROSS APPLY
    (
      SELECT
        City    = SUBSTRING(f.String, a.Head,  a.Pos-1),
        [State] = SUBSTRING(f.String, a.Pos+1, b.Pos-a.Pos-1), 
        Zip     = SUBSTRING(f.String, b.Pos+1, c.Pos-b.Pos-1),
        Country = SUBSTRING(f.String, c.Pos+1, 200)
      FROM        (VALUES(RTRIM(LTRIM(REPLACE(REPLACE(
                   t.BILLING_CITYSTATEZIP,', ',','),' ,',','))))) AS f(String)
      CROSS APPLY (VALUES(CHARINDEX(',',f.String),1))            AS a(Pos,Head)
      CROSS APPLY (VALUES(CHARINDEX(' ',f.String,a.Pos+1)))      AS b(Pos)
      CROSS APPLY (VALUES(CHARINDEX(',',f.String,b.Pos+1)))      AS c(Pos)
    ) AS f;
    

    返回:

    SomeId   City       State  Zip    Country
    -------- ---------- ------ ------ ----------------
    1        Columbus   OH     43219  United States
    2        Chicago    IL     60625  United States
    

    【讨论】:

      猜你喜欢
      • 2013-02-08
      • 2014-01-31
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 2023-02-21
      • 1970-01-01
      • 2020-04-21
      • 1970-01-01
      相关资源
      最近更新 更多