I’d like to split the result from a query and display the values in separate columns. As an example I get the following result
|Name | |ABC_DEFG_HIJKL| |A_B_C | |A_B_C_D |
I want to split the values by ‘_’ and add them to separate columns. The query result should look something like this
|Name |first |second |third |fourth| |ABC_DEFG_HIJKL|ABC |DEFG |HIJKL |null | |A_B_C |A |B |C |null | |A_B_C_D |A |B |C |D |
So far I can split the result. But for each value, I have a new row. So I just need to merge the results into one row and make a column for each of those rows.
SELECT DP.Name, value FROM RitopDatenpunkt DP CROSS APPLY STRING_SPLIT(DP.Name, '_'); |Name |value | |ABC_DEFG_HIJKL|ABC | |ABC_DEFG_HIJKL|DEFG | |ABC_DEFG_HIJKL|HIJKL | |A_B_C |A | |A_B_C |B | |A_B_C |C | |A_B_C_D |A | |A_B_C_D |B | |A_B_C_D |C | |A_B_C_D |D |
I know that I should use PIVOT. But what aggragate function do I use and are the arguments for the FOR statement right
SELECT DP.Name, value FROM RitopDatenpunkt DP CROSS APPLY STRING_SPLIT(DP.Name, '_') PIVOT ( GROUPING(Name) as Name FOR value in ([first],[second],[third],[fourth]) )piv;
Advertisement
Answer
Here is one way to do it using JSON functions:
select t.name, json_value(x.obj, '$[0]') name1, json_value(x.obj, '$[1]') name2, json_value(x.obj, '$[2]') name2, json_value(x.obj, '$[3]') name4 from mytable t cross apply (values('["' + replace(t.name, '_', '", "') + '"]')) x(obj)
The trick is to manipulate the string to make it look like a JSON array (that’ what the cross apply
subquery does). Basically this turns a string like 'A_B_C'
to '["A", "B", "C"]'
. We can then use json_value()
to easily access each individual element.
This does not assume anything about the elements being unique. Actually the only requirement is that the string should not contain embedded double quotes.
name | name1 | name2 | name2 | name4 :------------- | :---- | :---- | :---- | :---- ABC_DEFG_HIJKL | ABC | DEFG | HIJKL | null A_B_C | A | B | C | null A_B_C_D | A | B | C | D