【问题标题】:How to split string to takeout a specific part in SQL?如何拆分字符串以取出 SQL 中的特定部分?
【发布时间】:2018-01-11 18:40:33
【问题描述】:

我想将地址拆分为Street NumberStreet Name

样本数据

  • 1093百行路
  • 4442 号公寓 Holly StreetAvondale
  • 1401/142 号公寓莎士比亚路
  • Unit K109 Northbridge 45 Akoranga Drive, Northcote

在这些示例中,粗体部分为Street Number,其余部分为Street Name

到目前为止,我目前的努力对我没有帮助。有没有人能快速解决这个问题?

-Key 是地址的Street Number 部分,在最后一次出现Number 的地方结束。

【问题讨论】:

  • 您的数据是否总是由 Streen Number 组成?它总是以数字结尾吗?
  • 你打算为 1200 5th St(导致th St)或 400 Main St PO Box 123 Springfield PA(Springfield PA)做什么?
  • 第 5 次.... 整个词应该有效。不做邮箱地址。

标签: sql sql-server string tsql split


【解决方案1】:

如果字符串的模式一致,可以使用

select 
ltrim(rtrim(reverse(substring(reverse(address),patindex('%[0-9]%',reverse(address)),len(address))))) as streetNum,
ltrim(rtrim(reverse(substring(reverse(address),1,patindex('%[0-9]%',reverse(address))-1)))) as streetName
from tbl

使用patindex 查找反转字符串中第一个数字的出现,并使用substringreverse 将它们拆分为单独的字段。

【讨论】:

  • 谢谢,vkp。为努力而投票。验证结果 atm。 :)
  • 我的示例对于我刚刚发现的新地址模式还不够丰富,但我可以从这里开始工作。对于给定的样本,@vkp 和 John 的答案几乎都是正确的,但将 John 的回复标记为标记的答案以获取更多详细信息。希望 vkp 可以接受吗?
【解决方案2】:

示例

Declare @YourTable Table ([Id] varchar(50),[Addr] varchar(50))
Insert Into @YourTable Values 
 (1,'1093 Hundred Line Road')
,(2,'Flat 4442 Holly StreetAvondale')
,(3,'Apartment 1401/142 Shakespeare Road')
,(4,'Unit K109 Northbridge 45 Akoranga Drive, Northcote')

Select ID 
      ,Addr1 = left(Addr,len(Addr)-patindex('%[0-9]%',reverse(Addr))+1)
      ,Addr2 = ltrim(right(Addr,patindex('%[0-9]%',reverse(Addr))-1))
 From @YourTable

或者只是为了好玩 - 使用交叉应用

Select ID 
      ,Addr1 = substring(Addr,1,B.Pos)
      ,Addr2 = ltrim(substring(Addr,B.Pos+1,100))
 From @YourTable
 Cross Apply (values (len(Addr)-patindex('%[0-9]%',reverse(Addr))+1)) B(Pos)

退货

ID  Addr1                       Addr2
1   1093                        Hundred Line Road
2   Flat 4442                   Holly StreetAvondale
3   Apartment 1401/142          Shakespeare Road
4   Unit K109 Northbridge 45    Akoranga Drive, Northcote

我要注意:

解析地址可能是一个滑坡。考虑以下几点:Address standardization within a database

【讨论】:

  • 谢谢,约翰。同意标准化,但数据来自 7 个不同的系统,有 30 年以上的旧记录和 70k 多个客户。一切都分为 Address1Line1、Address1Line2、Address1Line3、Address1Line4、PostCode1、City1、Suburb1、Country1 和 N 个地址。但是数据输入问题会导致愚蠢的问题。
  • 谢谢,约翰。为努力点赞。验证结果 atm。 :)
  • @Viking 乐于助人
  • 我的示例对于我刚刚发现的新地址模式还不够丰富,但我可以从这里开始工作。对于给定的样本,@vkp 和 John 的答案几乎都是正确的,但将 John 的回复标记为标记的答案以获取更多详细信息。希望 vkp 可以接受吗?
【解决方案3】:

另一种选择...

IF OBJECT_ID('tempdb..#Address', 'U') IS NOT NULL 
DROP TABLE #Address;

CREATE TABLE #Address (
    StreetAddress VARCHAR(50) NOT NULL 
    );
INSERT #Address (StreetAddress) VALUES
    ('1093 Hundred Line Road'),
    ('Flat 4442 Holly StreetAvondale'),
    ('Apartment 1401/142 Shakespeare Road'),
    ('Unit K109 Northbridge 45 Akoranga Drive, Northcote');

--  SELECT * FROM #Address a;

--========================================================

SELECT 
    *,
    StreetNum = LEFT(a.StreetAddress, sl.SplitLocation),
    StreetName = SUBSTRING(a.StreetAddress, sl.SplitLocation + 1, 50)
FROM
    #Address a
    CROSS APPLY ( VALUES (PATINDEX('%[^0-9] [0-9]%', REVERSE(a.StreetAddress))) ) rs (ReverseSplit)
    CROSS APPLY ( VALUES (LEN(a.StreetAddress) - rs.ReverseSplit) ) sl (SplitLocation);

HTH,杰森

【讨论】:

  • 谢谢,杰森。为努力点赞。验证结果虽然:)
猜你喜欢
  • 2017-11-15
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
  • 2016-11-09
相关资源
最近更新 更多