0

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?

6
  • You're passing a comma to STRING_SPLIT as the delimiter, and yet in your example, you seem to want to split by a space. Also, why not pass [City_St_Zip] to the function instead of @X? Also, you should consider how to handle cities that have more than one word in the name if you indeed want to split by a space. Commented Dec 20, 2019 at 23:17
  • Your select columns do not include the value output from string_split which is going to be null in this case because you're trying to split @x instead of your City_St_Zip column. See the String_Split docs, https://learn.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql Commented Dec 20, 2019 at 23:20
  • @devlincarnate I tried what you suggested please see the updated question Commented Dec 20, 2019 at 23:38
  • @AlwaysLearning that was an oops on my part thank you for pointing that out I fixed it Commented Dec 20, 2019 at 23:39
  • String split is wrong. Fort Worth, TX 00000 will break Commented Dec 20, 2019 at 23:47

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Would this apply when getting the original value from a table column. For example dbo.Invoice.[City_St_Zip]? Other than that it works perfectly
@MaxG . . . Yes. The db<>fiddle essentially shows that (the column is named col).
0

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;

3 Comments

This is very close but as mentioned in the comments on my question Fort Worth, TX 12345 comes out like Fort is the City, Worth is the state and TX is the zip code. How would I accommodate for the space in city names
Perfect!! Thank you! I had no idea the amount of work just to parse that out.
It used to be worse. There's also alternatives by using the XML type. But I would cheer if MS would someday include something like the MySql SUBSTRING_INDEX.
0

* 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.