拆分地址

时间:2017-03-02 22:07:20

标签: mysql sql

我正试图找到一种方法将地址栏分成两部分,以便分隔街道号码,街道名称,城市和州。

SELECT distinct
            OWNER,
            ADDRESS,

FROM vw_EMPLOYEE

这给我一个像这样的结果

OWNER   ADDRESS           
JOHN    10 HILL MIAMI FL 33139
TONY    4545 BIRD AVE DORAL FL 33134

在5个不同的列中拆分此列的最佳选择是什么? 我正在阅读有关函数或子子字符串但我有点困惑,因为我还在学习SQL

6 个答案:

答案 0 :(得分:1)

您可以使用this udfdetailed in this answer to your question按空格分割地址字段,然后使用每个元素。但是这有问题:

  • 你的地址不一致(有些地方没有其他国家) - 它很乱。
  • 无论地址中的字数是多少,udf和sql都不允许您轻松遍历地址中的每个字(UDF要求您指定“字数”)。

如果我遇到这个问题,我会使用脚本语言而不是SQL来分割和循环遍历地址字段中的每个单词。按照这样的过程:

  1. 将zipcodes列表导入表格。

  2. 将状态和州缩写列表导入表格。

  3. 将城市列表输入表格。

  4. 将道路名称和缩写列表输入表格(例如,road,rd,street,st)。

  5. 按空格分割地址,然后从最后一个地址字循环到第一个:

    一个。如果邮政编码表中存在该单词,那么这就是邮政编码。如果已经为当前地址识别了邮政编码,则会出错。

    湾否则,如果状态表中存在该单词,那么这就是状态。如果已经为当前地址确定了状态,那么就是错误。

    ℃。否则,如果城市名称表中存在该词,那么这就是城市。如果已经为当前地址识别了城市,则会出错。

    d。否则,如果道路名称表中存在该词,则当前词和所有先前词将被假定为地址线。

    即在a-d中概述的if / else块之外,如果为当前地址识别了zipcode,state和city,则假设剩余的单词形成地址行1.

  6. 上述过程将为您提供一个有问题的清洁之旅的开始。

    您可能需要解决的其他一些问题:

    • 如果地址碰巧有“,”分隔字段元素,您可能需要将它们剥离。例如:10 HILL MIAMI,FL,33139

答案 1 :(得分:1)

您可以create function

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       CHAR_LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, "");

查询:

select distinct
            OWNER,prod_id,SPLIT_STR(ADDRESS,' ',1) as pos1 ,SPLIT_STR(ADDRESS,' ',2) as pos2,
SPLIT_STR(ADDRESS,' ',3) as pos3 ,SPLIT_STR(ADDRESS,' ',4) as pos4,SPLIT_STR(ADDRESS,' ',5) as pos5
from vw_EMPLOYEE

答案 2 :(得分:0)

  

当存在分界符时,分裂更容易。在SUBSTRINGPATINDEX

的帮助下

由于您的ADDRESS专栏没有这样的内容,您可以选择此项。这将首先转换为xml,然后从那里你可以在5个不同的列中实现该值。

;WITH Split_Address (Owner,Address, xmladd)
 AS
(
    SELECT Owner,
    Address,
    CONVERT(XML,'<Adrdress><Adrdress>'  
    + REPLACE(Adrdress,' ', '</Adrdress><Adrdress>') + '</Adrdress></Adrdress>') AS xmladd
     FROM (select Adrdress,Owner from vw_EMPLOYEE)as t
)

 SELECT Value,      
    xmlname.value('/Adrdress[1]/Adrdress[1]','varchar(100)') AS Adrdress1,    
    xmlname.value('/Adrdress[1]/Adrdress[2]','varchar(100)') AS Adrdress2,
    xmlname.value('/Adrdress[1]/Adrdress[3]','varchar(100)') AS Adrdress3,
    xmlname.value('/Adrdress[1]/Adrdress[4]','varchar(100)') AS Adrdress4,
    xmlname.value('/Adrdress[1]/Adrdress[5]','varchar(100)') AS Adrdress5
 FROM Split_Address 

答案 3 :(得分:0)

我认为不能保证你总是有5个部分。像123 Santa Rosa Blvd. CA 91035这样的地址有六个部分。

一般

  1. 第一个空格之前的所有内容,可以是NUMBER
  2. 最后一个空格之前的所有内容都可以是ZIPCODE
  3. 删除这两部分后,您将最后两个字符作为STATE
  4. 其余的将是STREET。
  5. 希望这会引导您进行算法。

答案 4 :(得分:0)

谢谢大家的反馈。所有的回应都帮助了我并引导我找到了正确的方向。我认为最好的是功能创建。

答案 5 :(得分:0)

只需添加更多反馈...

您应该准备按可能的值顺序解析地址。 这是可能的故障

**

  

PreCoor Coor PostCoor街道编号方向街道名称街道后缀   PostDirection UnitType UnitNumber

**

PreCoor,PostCoor,Direction和PostDirection是方向(N,S,E或W)

带区号的地址以逗号和句号开头

您将不得不对可能的单元名称(单元,#,APT等...)进行正则表达式或循环浏览,并且以下Unit_Number可以为数字[0-9]或基于字母的[az]或两者兼而有之。它们的长度通常也可以是1-5个字符。

您还将需要检查地址中可能的邮政信箱。如果找到了,其他的都没关系。

通常,在其各自的字段中提供城市,州和邮政编码。

关于拆分UNIT的示例 mySQL

  

REPLACE(REPLACE(REPLACE(ADDR,'。',''),'-',''),',','')REGEXP'(UNIT |   APT | #|套房| STE | LOT)?([0-9] {1,5} $ | [a-z] {1,4} $)';

php

  

preg_match('/(UNIT | APT |#| SUITE | STE | LOT)   ?([a-z] {1,3} | [0-9] {1,3})/ i',$ input_line,$ output_array);