Reputation: 85
How to split a col in sql server based on a delimiter?
I tried using STRING_SPLIT()
function:
select *
from TABLE1
CROSS APPLY STRING_SPLIT(city, ',' ).
I was getting a invalid object name string_split error. I don't want to use a complex procedure to solve this as it's a one time thing. Are there other better methods or functions catered for such purposes in SQL Server?
Input: TABLE1
name | age | city | dept
RACHEL | 43 | NJ, WH | AUTO
Rob | 12 | NY, CALI, TX | WEB
Ashley | 23 | CN | KYO
Laine | 22 | | KK
Reeza | 45 | NULL | AUTO
Output:
nam e | age | city | dept
RACHEL | 43 | NJ | AUTO
RACHEL | 43 | WH | AUTO
Rob | 12 | NY | WEB
Rob | 12 | CALI | WEB
Rob | 12 | TX | WEB
Ashley | 23 | CN | KYO
Laine | 22 | | KK
Reeza | 45 | NULL | AUTO
Upvotes: 0
Views: 502
Reputation: 1269483
Use string_split()
:
select t.name, t.age, trim(s.value) as city, t.dept
from t cross apply
string_split(t.city, ',') s;
I'm not sure why this would produce an error. A more complex method uses a recursive CTE:
with cte as (
select t.name, t.age, convert(varchar(max), NULL) as city, t.dept, 1 as lev, convert(varchar(max), t.city) as rest
from t
union all
select name, age, trim(left(rest, charindex(',', rest + ',') - 1)),
dept, lev + 1, stuff(rest, 1, charindex(',', rest + ','), '')
from cte
where rest <> ''
)
select name, age, city, dept
from cte
where city is not null;
Here is a SQL Fiddle.
Upvotes: 1
Reputation: 22157
It seems that your SQL Server version is below 2016. That's why the STRING_SPLIT()
function is not supported.
SELECT @@VERSION;
will help to identify the version.
Here is another approach based on XML and XQuery. It will work on SQL Server 2008 onwards.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, [name] VARCHAR(20), age INT, city VARCHAR(100), dept VARCHAR(10));
INSERT INTO @tbl (name, age, city, dept) VALUES
('RACHEL', 43 , 'NJ, WH','AUTO'),
('Rob', 12 ,'NY, CALI, TX','WEB '),
('Ashley', 23 , 'CN','KYO'),
('Laine', 22 , '', 'KK'),
('Reeza', 45 , NULL,'AUTO');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = ',';
;WITH rs AS
(
SELECT *
, CAST('<root><r><![CDATA[' +
REPLACE(SPACE(1) + city, @separator, ']]></r><r><![CDATA[') + ']]></r></root>' AS XML) AS xmldata
FROM @tbl
)
SELECT id, name, age
, LTRIM(c.value('(./text())[1]','VARCHAR(100)')) AS city
, dept
FROM rs
OUTER APPLY xmldata.nodes('/root/r') t(c);
Output
+----+--------+-----+------+------+
| id | name | age | city | dept |
+----+--------+-----+------+------+
| 1 | RACHEL | 43 | NJ | AUTO |
| 1 | RACHEL | 43 | WH | AUTO |
| 2 | Rob | 12 | NY | WEB |
| 2 | Rob | 12 | CALI | WEB |
| 2 | Rob | 12 | TX | WEB |
| 3 | Ashley | 23 | CN | KYO |
| 4 | Laine | 22 | | KK |
| 5 | Reeza | 45 | NULL | AUTO |
+----+--------+-----+------+------+
Upvotes: 2