我有一个长字符串的列。数据需要拆分成列,并且有不同长度的字符串,它们的列数并不总是相同。不太确定如何做到这一点,所以在这里寻求一些建议。
假设我有这个字符串:
VS5~MedCond1~35.4|VS4~MedCond2~16|VS1~MedCond3~155|VS2~MedCond4~70|SPO2~MedCond5~100|VS3~MedCond6~64|FiO2~MedCond7~21|MAP~MedCond8~98|
在某些情况下,字符串可能不会包含所有的医疗条件,只是其中的一部分。
我需要将列名分成几列,其中列名在tild之间,即MedCond1,值将是tild右侧但在管道之前的值,最后如下所示:
MedCond1 MedCond2 MedCond3 MedCond4 MedCond5 MedCond6 MedCond7 MedCond8
======== ======== ======== ======== ======== ======== ======== ========
35.1 24 110 64 100 88 21 79我需要对大表中的许多行执行此操作,正如我所说的,并不是所有的列都存在,但它们不会是不同的名称,您可能已经完成了med 1- 8,然后在另一个集合中具有med 3,4,7。
下面是我创建的一个查询,它是我想要的,但不是动态的,所以它通过字符串的一些额外部分来提取值
select MainCol, case when charindex('MedCond1', MainCol) > 0 then
substring(MainCol, charindex('MedCond1', MainCol) + 9, 4) end as [MedCond1]
from MedTable将会返回
MedCond1
========
35.3
40.2
33.6
33|V <--- Problem正如您所看到的,由于charindex数字的硬编码,有时会使用字符串的附加部分来提取数字值。值的长度有时为4个字符,带小数位,有时为2个字符,不带小数位。我想让它具有动态性。管道定义了我需要的数据的结尾,起始是由列名称末尾的tild定义的。
感谢您对此进行动态化的任何想法
安德鲁
发布于 2017-03-15 20:48:49
这些数据看起来就像一个表本身。它可以作为xml存储在SQL Server中。SQL Server支持xml字段并允许对其进行查询。实际上,您可以尝试将此字符串转换为XML,然后尝试查询它:
declare @medTable table (item nvarchar(2000))
insert into @medTable
values ('VS5~MedCond1~35.4|VS4~MedCond2~16|VS1~MedCond3~155|VS2~MedCond4~70|SPO2~MedCond5~100|VS3~MedCond6~64|FiO2~MedCond7~21|MAP~MedCond8~98|');
-- Step 1: Replace `|` with <item> tags and `~` with `tag` tags
-- This will return an xml value for each medTable row
with items as (
select xmlField= cast('<item><tag>'
+ replace(
replace(item,'|','</tag></item><item><tag>'),
'~','</tag><tag>' )
+ '</tag></item>' as xml)
from @medTable
)
-- Step 2: Select different tags and display them as fields
select
y.item.value('(tag/text())[1]','nvarchar(20)'),
y.item.value('(tag/text())[2]','nvarchar(20)'),
y.item.value('(tag/text())[3]','nvarchar(20)')
from items outer apply xmlField.nodes('item') as y(item)结果是:
-------------------- -------------------- -------
VS5 MedCond1 35.4
VS4 MedCond2 16
VS1 MedCond3 155
VS2 MedCond4 70
SPO2 MedCond5 100
VS3 MedCond6 64
FiO2 MedCond7 21
MAP MedCond8 98
NULL NULL NULL不过,最好在加载数据时执行此转换。例如,在C#或SSIS中进行替换并将完整的XML值存储在数据库中会更容易。
您还可以修改此查询,以生成XML值并将其存储在数据库中:
declare @medTable2 table (xmlField xml)
with items as (
select xmlField= cast('<item><tag>' + replace(replace(item,'|','</tag></item><item><tag>'),'~','</tag><tag>' ) + '</tag></item>' as xml)
from @medTable
)
insert into @medTable2
select items.xmlField
from items
-- Query the new table from now on
select
y.item.value('(tag/text())[1]','nvarchar(20)'),
y.item.value('(tag/text())[2]','nvarchar(20)'),
y.item.value('(tag/text())[3]','nvarchar(20)')
from @medTable2 outer apply xmlField.nodes('item') as y(item)发布于 2017-03-15 20:44:28
好的,让我来试一试。我概述的解决方案不会是纯粹的SQL Server,但是,它通过文本文件使用往返。
该方法使用以下步骤:
将由竖线符号分隔的数据(为每行输入创建多行输出)将数据从SQL Server返回到文本文件,然后在代字号符号分隔符上将数据返回到列中
~ 这种方法的主要优点是unpivot操作,它允许您在缺少等效行的情况下自然地处理缺少的列,如MedCond2。它还消除了几乎所有的字符串操作,除了下面步骤1中的一个REPLACE函数。
给定单行内容,如下所示:
VS5~MedCond1~35.4|VS4~MedCond2~16|VS1~MedCond3~155|VS2~MedCond4~70|SPO2~MedCond5~100|VS3~MedCond6~64|FiO2~MedCond7~21|MAP~MedCond8~98| 取消旋转步骤1():查找管道符号的所有实例,并将其替换为换行符。因此,对于单个输入行,REPLACE(column, '|', CHAR(13))将为您提供以下文本行(即,单个数据库行中的多行文本):
VS5~MedCond1~35.4
VS4~MedCond2~16
VS1~MedCond3~155
VS2~MedCond4~70
SPO2~MedCond5~100
VS3~MedCond6~64
FiO2~MedCond7~21
MAP~MedCond8~98步骤2(往返):使用您选择的工具(SSIS、SQLCMD等)将上述输出写入一个文本文件。并确保定义的换行符与步骤1中的REPLACE命令中使用的换行符相同。
此步骤的目的是将同一行中的多条线路与不同行中的其他线路连接起来。
请注意,可以通过将步骤2和3的行分隔符定义为管道符号来消除步骤1。我添加了额外的步骤1,使用换行符只是为了使其更容易理解和调试。
步骤3(分栏):使用相同的工具将文本文件重新导入SQL Server,并将列分隔符定义为代字号~符号,行分隔符的定义与步骤1/2相同。
ColA MedCondTitle MedCondValue
------ ------------- -------------
VS5 MedCond1 35.4
VS4 MedCond2 16
VS1 MedCond3 155
VS2 MedCond4 70
SPO2 MedCond5 100
VS3 MedCond6 64
FiO2 MedCond7 21
MAP MedCond8 98步骤4(透视):现在您已经有了将行旋转为列的简单步骤,这可以通过以下形式的语句来实现:
SUM(CASE WHEN MedCondTitle='MedCond1' THEN MedCondValue ELSE 0) as MedCond1 https://stackoverflow.com/questions/42791402
复制相似问题