Home > OS >  String Splitting an Array
String Splitting an Array

Time:07-22

I've got a column in a database table that is stored like the below that I'm trying to split out into columns to be able to report on it a lot easier:

  Question 1 : ["Yes","","b1"];  Question 2 : ["","No","b2"];  Question 3: ["Yes","","b3"];  Question 4: ["","No",""];  Question 5: ["Yes","","b5"];  Question 6: ["","No","b6"];  Question 7: ["Yes","","b7"];  

From the below table, I've got this so far:

SELECT
    *,
    CASE 
        WHEN LEN(ItemValues) > 1 THEN 
            LEFT(ItemValues, charindex(':', ItemValues) - 1)
    END as Question,
    '' as Answer,
    '' as Comment
FROM 
(
    SELECT 
        ID,
        TRIM(value) as ItemValues
    FROM 
        #StackQuestion
    CROSS APPLY STRING_SPLIT(Response,';')
) t1
where
    LEN(ItemValues) > 1

What I'm really struggling with is populating the Answer and Comment columns. The Answer column should contain "Yes" or "No", and the Comment column should contain the final part which is b1 for example.

Any ideas?

Create Table #StackQuestion
(
    ID int IDENTITY(1,1), 
    Response varchar(2000) 
)

insert into #StackQuestion
(
    Response
)
select
'
Question 1 : ["Yes","","b1"]; 
Question 2 : ["","No","b2"]; 
Question 3: ["Yes","","b3"]; 
Question 4: ["","No",""]; 
Question 5: ["Yes","","b5"]; 
Question 6: ["","No","b6"]; 
Question 7: ["Yes","","b7"]; 
'
union all
select
'
Question 1 : ["","No","comment1"]; 
Question 2 : ["","No","c2"]; 
Question 3: ["Yes","","c3"]; 
Question 4: ["Yes","","c4"]; 
Question 5: ["Yes","","b5"]; 
Question 6: ["","No","b6"]; 
Question 7: ["Yes","","b7"]; 
'

CodePudding user response:

I had a quick play around with some additional string manipulation, perhaps something like the following will work for you?

select ID, 
  Trim(Left(ItemValues, CharIndex(':', ItemValues) - 1)) as Question,
  case when ItemValues like '%"Yes"%' then 'Yes' else 'No' end as Answer,
  comment
from #StackQuestion
cross apply (
  select value as ItemValues, Reverse(Left(c, CharIndex('"',c) -1)) comment
  from String_Split(Response, ';')
  cross apply(values(Reverse(Replace(value, '"]',''))))v(c)
  where Len(value) > 3
)r;

Note that although in practice you will probably be ok, using string split is documented to not be relied upon for ordering.

CodePudding user response:

Since the answers list to each of the questions is actually valid JSON syntax, you can use the OPENJSON function, which will output the answers as different records. The PIVOT operator can be used to get the values on the same line again.

Here is an adaptation of the code that does the job. Note that I replaced the len(ItemValues) > 1 condition with charindex(':', ItemValues) >= 1 in order to get rid of errors on white space strings that were longer than 1 character.

with prep as (
    SELECT
        *,
        LEFT(ItemValues, charindex(':', ItemValues) - 1) as Question,
        substring(ItemValues, charindex(':', ItemValues)   1, 999) as Answers
    FROM 
    (
        SELECT 
            ID
            ,
            TRIM(value) as ItemValues
            --ca1.ItemValues
        FROM 
            #StackQuestion
        CROSS APPLY STRING_SPLIT(Response,';') -- ca1(ItemValues)
    ) t1
    where
        charindex(':', ItemValues) >= 1
)
select
    answer = [0]   [1],
    comment = [2]
from (
    SELECT
        * 
    from prep
    cross apply OPENJSON(Answers)
) as answers
pivot ( 
    max([value]) 
    for [key] in ([0], [1], [2])
) piv

Output:

answer comment
Yes b1
No b2
Yes b3
No
Yes b5
No b6
Yes b7
No comment1
No c2
Yes c3
Yes c4
Yes b5
No b6
Yes b7
  • Related