SQL 从字符串中提取值

Posted

技术标签:

【中文标题】SQL 从字符串中提取值【英文标题】:SQL Extract Values from a String 【发布时间】:2016-06-07 21:41:24 【问题描述】:

如何从字符串中提取值?我正在尝试分成 3 个新列。城市、州和邮政编码的单独列。

我试过了

select address2,
left(address2, charindex('',address2)-1)
from table

并且---当我尝试下面的代码时,我得到“传递给左侧或子字符串函数的长度参数无效”

,LTRIM(substring(a.Address2, CHARINDEX(' ', a.Address2)+1, CHARINDEX(' ', substring(a.address2, charindex(' ',
a.address2)+1, len(a.address2)))-1))

我可以使用以下代码拆分城市(西沃里克除外),但不确定如何使其适用于州和邮政编码。这也消除了错误。

SUBSTRING(Address2,1,CHARINDEX(' ', a.address2+ ' ')-1) as city

有什么想法可以尝试吗?

【问题讨论】:

【参考方案1】:

您的邮政编码和各州的长度似乎都相同。如果这是真的,你应该可以使用这样的东西:

SELECT
    LEFT(a.Address2,LEN(a.Address2) - 13) AS City,
    RIGHT(LEFT(a.Address2,LEN(a.Address2) - 11),2) AS State,
    RIGHT(a.Address2,10) AS Zip_Code
FROM
    table;

演示代码

创建表和数据:

CREATE TABLE MyTable (Address2 VARCHAR(100));

INSERT INTO MyTable
VALUES
    ('SAN DIEGO CA 92128-1234'),
    ('WEST WARWICK RI 02893-1349'),
    ('RICHMOND IN 47374-9409');

查询:

SELECT
    LEFT(Address2,LEN(Address2) - 13) AS City,
    RIGHT(LEFT(Address2,LEN(Address2) - 11),2) AS State,
    RIGHT(Address2,10) AS Zip_Code
FROM
    MyTable;

输出:

【讨论】:

我必须要有 where 子句吗?我仍然收到“传递给 LEFT 或 SUBSTRING 函数的长度参数无效。” 我确实更新了 State 逻辑 - 我差了一个。如果您仍然收到错误,这意味着有记录的 statezip(或两者)与您提供的示例数据中的长度不同。 这似乎消除了错误,但我只知道如何使它适用于一列。 (除了西华威)SUBSTRING(Address2,1,CHARINDEX(' ', address2+ ' ')-1) as city 不确定您为什么要使用 SUBSTRING 和 CHARINDEX,因为我在回答中没有建议。我也更新了我的答案,以包括每个步骤和输出。 感谢您的回答和回复,感谢您对我的帮助。我继续收到错误消息,所以我继续工作。上面的示例数据只是一个子集,作为我必须使用的示例。我需要为美国的每个城市、州和邮编创建一个临时表才能完成这项工作。我不确定我想这样做。任何其他建议或方法来完成这项工作。谢谢。【参考方案2】:

由于您只有 3 个部分(城市/州/邮编),您可以利用 SQL Server 2008 及更高版本中称为 parsename 的函数。 (该函数的初衷是解析出对象名。)

使用 replaceparsename 函数的组合将允许您将数据分成 3 个部分,即使状态(不太可能)或 Zip(更有可能)的长度发生变化。

示例数据:

create table #my_table
    (
        address2 varchar(75) not null
    )

insert into #my_table values ('CONNERSVILLE IN 47331-3351')
insert into #my_table values ('WEST WARWICK RI 02893-1349')
insert into #my_table values ('RICHMOND IN 47374-9409')
insert into #my_table values ('WILLIAMSBURG IN 47393-9617')
insert into #my_table values ('FARMERSVILLE OH 45325-9226')
--this record is an example of a likely scenario for when the zip length would change.
insert into #my_table values ('WILLIAMSBURG IN 47393')

解决方案:

with len_vals as 
    (
        select t.address2
        , len(parsename(replace(t.address2,' ','.'), 1)) as zip_len
        , len(parsename(replace(t.address2,' ','.'), 2)) as st_len
        from #my_table as t
        group by t.address2
    )
select left(a.address2, len(a.address2) - b.zip_len - b.st_len  - 2) as city
, substring(a.address2, len(a.address2) - b.zip_len - 2, b.st_len) as st
, right(a.address2, b.zip_len) as zip_code
from #my_table as a
inner join len_vals as b on a.address2 = b.address2

结果:

【讨论】:

以上是关于SQL 从字符串中提取值的主要内容,如果未能解决你的问题,请参考以下文章

sql中如何提取从数据库中所获得时间的年份

在变量中使用引号在 SQL 中构造字符串 [重复]

sql 提取第一个字符

在 SQL 中的两个相同字符之间提取值

bigquery 标准 sql = 从字符串中提取数据

c#从字符串中提取sql查询部分