解析单元格中的文本并将其转换为多列中的数据
Posted
技术标签:
【中文标题】解析单元格中的文本并将其转换为多列中的数据【英文标题】:Parsing the text in a cell and converting it into data in multiple columns 【发布时间】:2020-03-07 17:44:33 【问题描述】: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;
但这仅适用于第一行。
【问题讨论】:
这会很痛苦,尤其是对于没有适当正则表达式支持的 SQL Server。这项任务在应用程序端会更容易完成。 您应该从一开始就规范化架构并使用不同的列。 【参考方案1】:您可以拆分字符串并在 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
编辑 - 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
【讨论】:
谢谢伙计。有用。你能给我解释一下Cross Apply ( Select Summary= stuff(max(case when charindex('Summary:',value)>0 then Value end),1,10,'')
吗?这是如何运作的?或者,如果您可以参考任何文档。
@PrateekSharma 总是乐于提供帮助。看看dbfiddle.uk/… 你会看到只有 string_split() 的 CROSS APPLY 会生成多行。我们只取这些行并应用条件聚合,同时去掉“Summary”、“Steps”和“Result”
在不创建函数的情况下,SQL Server 2012 是否有替代方案?
@PrateekSharma 当然,请参阅编辑部分。【参考方案2】:
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
想法是从您的descriptions
之一获取 JSON 字符串,然后对其进行解析并提取相关字段,例如
#*Summary: data1 #*Steps: data2 #*Result: data3
变成
"Summary":"data1","Steps":"data2","Result":"data3"
当然有一些注意事项,主要取决于您在表中实际拥有的值。
【讨论】:
以上是关于解析单元格中的文本并将其转换为多列中的数据的主要内容,如果未能解决你的问题,请参考以下文章
点击保存按钮并存储在字典中时获取表格视图单元格中的文本字段?