【问题标题】:How to parse out a column in sql with multiple values如何在sql中解析出具有多个值的列
【发布时间】:2019-12-20 22:59:02
【问题描述】:

我在名为 [City_St_Zip] 的 sql server 表中有一个列,其中包含如下所示的记录

达拉斯,德克萨斯州 12345

我想做的是将该列分成三个不同的列(即城市、州和邮编) 像这样:

达拉斯

发送

12345

我不知道如何在 SQL 中解决这个问题

我已经尝试了以下

DECLARE @X NVARCHAR(100),
DECLARE @T NVARCHAR(100),
SELECT
   @X = [City_St_Zip],
   @T = [NewDivision]
FROM
   dbo.Invoice
      CROSS APPLY STRING_SPLIT(@X, ',');

这产生了 0 个结果,所以我很确定我做错了

有什么建议吗?我正在使用 SQL Server 2019

编辑: 我也试过这个更接近我想要的

SELECT 
   value
FROM
  dbo.Invoice
   CROSS APPLY STRING_SPLIT([City_St_Zip], ',');

这给了我一个结果集:

达拉斯

TX 12345

所以我猜这很复杂,需要逗号和空格分隔符。我可以将值放入另一个 STRING_SPLIT 吗?

【问题讨论】:

  • 您将逗号传递给 STRING_SPLIT 作为分隔符,但在您的示例中,您似乎想用空格分隔。另外,为什么不将[City_St_Zip] 传递给函数而不是@X?此外,如果您确实想用空格分割,您应该考虑如何处理名称中包含多个单词的城市。
  • 您的选择列不包括来自string_splitvalue 输出,在这种情况下将是null,因为您尝试拆分@x 而不是您的City_St_Zip柱子。请参阅 String_Split 文档,https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql
  • @devlincarnate 我尝试了你的建议,请查看更新后的问题
  • @AlwaysLearning 这对我来说是一个糟糕的事情,感谢您指出我已修复它
  • 字符串拆分错误。 Fort Worth, TX 00000 将破裂

标签: sql sql-server


【解决方案1】:

SQL Server 对字符串处理的支持很差。而且,string_split() 不能保证保持这些值的顺序。字符串搜索很危险——想想纽约,纽约。

所以,一种蛮力方法:

select left(col, charindex(',', col) - 1) as city,
       substring(col, charindex(',', col) + 2, 2) as state,
       right(col, 5) as zipcode

Here 是一个 dbfiddle。

【讨论】:

  • 从表格列获取原始值时是否适用。例如 dbo.Invoice.[City_St_Zip]?除此之外,它完美无缺
  • @MaxG 。 . .是的。 dbfiddle 基本上表明(该列名为 col)。
【解决方案2】:

如果你想使用STRING_SPLIT,那么这将在没有变量的情况下工作。

样本数据:

create table dbo.Invoice
(
  id int identity(1,1) primary key,
  [City_St_Zip] nvarchar(100)
);

insert into dbo.Invoice 
([City_St_Zip]) values
('Dallas, TX 12345'),
('Fort Worth, TX 12345')
GO
2 行受影响

查询:

SELECT inv.*, a.*
FROM dbo.Invoice inv
OUTER APPLY 
(
   SELECT
   [1] AS [City], 
   LTRIM(LEFT([2], 3)) AS [State],
   TRIM(SUBSTRING([2],4,LEN([2]))) AS [Zip]
   FROM
   ( SELECT spl.value
     , ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS rn
     FROM STRING_SPLIT(inv.[City_St_Zip],',') spl
   ) s
   PIVOT (MAX(value) FOR rn IN ([1],[2])) p
) a;

结果:

编号 | City_St_Zip |城市 |状态 |压缩 -: | :-------------------- | :--------- | :---- | :---- 1 |德克萨斯州达拉斯 12345 |达拉斯 |德克萨斯州 | 12345 2 |德克萨斯州沃思堡 12345 |沃思堡 |德克萨斯州 | 12345

db小提琴here

额外:

使用 XML 类型,此 SQL 也可以在 Sql Server 2012 等早期版本中运行。

SELECT inv.*
, a.City
, RTRIM(LEFT(a.StateZip, CHARINDEX(' ',a.StateZip))) AS State
, LTRIM(SUBSTRING(a.StateZip, CHARINDEX(' ',a.StateZip),LEN(a.StateZip))) AS Zip
FROM dbo.Invoice inv
OUTER APPLY
(
  SELECT X.x AS CityStateZipXml
  , X.x.value('/x[1]','nvarchar(max)') AS City
  , LTRIM(X.x.value('/x[2]','nvarchar(max)')) AS StateZip
  FROM (
    SELECT CAST(CONCAT('<x>', REPLACE(inv.[City_St_Zip],',','</x><x>'),'</x>') AS XML)
  ) AS X(x)
) a;

【讨论】:

  • 这非常接近,但正如我在问题 Fort Worth, TX 12345 中提到的那样,Fort 是城市,Worth 是州,TX 是邮政编码。我将如何适应城市名称中的空间
  • 完美!!谢谢!我不知道解析出来的工作量。
  • 以前更糟。也有使用 XML 类型的替代方法。但如果 MS 有朝一日会包含 MySql SUBSTRING_INDEX 之类的东西,我会很高兴。
【解决方案3】:

* 根据 SQL Server 更新*

create table ctry
( 
  city_st_zip nvarchar(100)
);

insert into ctry values('Dallas, TX 12345');

--使用的SQL--

SELECT
LEFT([city_st_zip], CHARINDEX(',', [city_st_zip]) - 1) AS [City],
SUBSTRING([city_st_zip], CHARINDEX(',', [city_st_zip]) + 2, 2) as [State],
RIGHT([city_st_zip], CHARINDEX(' ', [city_st_zip]) - 2) AS [Zip]
FROM ctry;

--结果--

City    State   Zip
Dallas  TX  12345

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    • 2015-04-03
    • 2022-12-11
    相关资源
    最近更新 更多