Reputation: 19
I have a column in a sql server table named [City_St_Zip] that contains records that look like this
Dallas, TX 12345
What I would like to do is separate the column into three different columns (i.e. City, State and Zip) like this:
Dallas
TX
12345
I am not sure how to go about this in SQL
I have tried the following
DECLARE @X NVARCHAR(100),
DECLARE @T NVARCHAR(100),
SELECT
@X = [City_St_Zip],
@T = [NewDivision]
FROM
dbo.Invoice
CROSS APPLY STRING_SPLIT(@X, ',');
This yielded 0 results so I am pretty sure I did that incorrectly
Any suggestions? I am using SQL Server 2019
EDIT: I also tried this which is closer to what I want
SELECT
value
FROM
dbo.Invoice
CROSS APPLY STRING_SPLIT([City_St_Zip], ',');
That gives me a result set of:
Dallas
TX 12345
So I guess this is convoluted and needs both a comma and a space delimiter. Would I just put the value through another STRING_SPLIT?
Upvotes: 0
Views: 1753
Reputation: 29647
If you want to use STRING_SPLIT
then this will work without variables.
Sample data:
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 rows affected
Query:
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;
Result:
id | City_St_Zip | City | State | Zip -: | :------------------- | :--------- | :---- | :---- 1 | Dallas, TX 12345 | Dallas | TX | 12345 2 | Fort Worth, TX 12345 | Fort Worth | TX | 12345
db<>fiddle here
Extra:
Using the XML type, this SQL will also work in an earlier version like 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;
Upvotes: 0
Reputation: 444
* Updated as per SQL Server*
create table ctry
(
city_st_zip nvarchar(100)
);
insert into ctry values('Dallas, TX 12345');
--SQL USED--
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;
--Result--
City State Zip
Dallas TX 12345
Upvotes: 0
Reputation: 1269823
SQL Server has poor string processing support. And, string_split()
is not guaranteed to keep the values in order. And string searches are dangerous -- think New York, New York.
So, a brute force method:
select left(col, charindex(',', col) - 1) as city,
substring(col, charindex(',', col) + 2, 2) as state,
right(col, 5) as zipcode
Here is a db<>fiddle.
Upvotes: 1