Разбор текста в ячейке и преобразование его в данные в нескольких столбцах - PullRequest
1 голос
/ 07 марта 2020
Table : test
|---------------------------------------------------------| 
|      descriptiona                                       |
|---------------------------------------------------------|
|#*Summary: data1  #*Steps: data2  #*Result: data3        |        
|---------------------------------------------------------|
|#*Steps: data5  #*Summary: data6  #*Result: data4        |
|---------------------------------------------------------|

Я хочу, чтобы данные отображались как:

summary   steps   result
data1     data2   data3
data6     data5   data4 

Пробовал с использованием:

SELECT  substring(descriptiona, 1, charindex('*Steps', descriptiona)-2) AS Summary,
  substring(descriptiona, charindex('*Steps', descriptiona), (charindex('*Result', descriptiona) - charindex('*Steps', descriptiona)) -2 ) AS Steps,
       substring(descriptiona, charindex('*Result', descriptiona),len(descriptiona)) AS ActualResult
 from test;

Но это работает только для первой строки.

Ответы [ 2 ]

1 голос
/ 07 марта 2020

Вы можете разбить строку и выполнить условное агрегирование в пределах CROSS APPLY

Пример

Declare @YourTable Table ([descriptiona] varchar(50))  Insert Into @YourTable Values 
 ('#*Summary: data1 #*Steps: data2 #*Result: data3')
,('#*Steps: data5 #*Summary: data6 #*Result: data4')

Select B.* 
 From  @YourTable
 Cross Apply ( Select Summary= stuff(max(case when charindex('Summary:',value)>0 then Value end),1,10,'')
                     ,Steps  = stuff(max(case when charindex('Steps:',value)>0 then Value end)  ,1,8,'')
                     ,Result = stuff(max(case when charindex('Result:',value)>0 then Value end) ,1,9,'')
                 From string_split([descriptiona],'#')
             ) B

Возвращает

Summary Steps   Result
data1   data2   data3
data6   data5   data4

EDIT - 2012 Нефункциональная альтернатива

Declare @YourTable Table ([descriptiona] varchar(50))  Insert Into @YourTable Values 
 ('#*Summary: data1 #*Steps: data2 #*Result: data3')
,('#*Steps: data5 #*Summary: data6 #*Result: data4')

Select B.* 
 From  @YourTable
 Cross Apply ( Select Summary= stuff(max(case when charindex('Summary:',value)>0 then Value end),1,10,'')
                     ,Steps  = stuff(max(case when charindex('Steps:',value)>0 then Value end)  ,1,8,'')
                     ,Result = stuff(max(case when charindex('Result:',value)>0 then Value end) ,1,9,'')
                 From (
                        Select seq   = row_number() over (order by 1/0)
                              ,value = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
                        From  (Select x = Cast('<x>' + replace((Select replace([descriptiona],'#','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                        Cross Apply x.nodes('x') AS B(i)
                      ) B1
             ) B
0 голосов
/ 07 марта 2020

SQL Fiddle

Просто для удовольствия, если вы используете SQL Server 2016 или более позднюю версию, это возможное решение (не самое симпатичное, по общему признанию):

SELECT
    JSON_VALUE(json_string, '$.Summary') as Summary,
    JSON_VALUE(json_string, '$.Steps') as Steps,
    JSON_VALUE(json_string, '$.Result') as Result
FROM (
        SELECT 
      '{"'+REPLACE(
        REPLACE(
          REPLACE(SUBSTRING(description, 3, LEN(description)), ' ', ''),
          ':', '":"'),
        '#*', '","') 
        + '"}' AS json_string
FROM test) A

Идея состоит в том, чтобы получить строку JSON из одного из ваших descriptions, а затем проанализировать ее как таковую и извлечь соответствующие поля, например,

#*Summary: data1  #*Steps: data2  #*Result: data3

становится

{"Summary":"data1","Steps":"data2","Result":"data3"}

Есть, конечно, несколько предостережений, в основном в зависимости от того, какие значения вы на самом деле имеете в своей таблице.

...