2015-07-02 36 views
0

我有一个旧的老式系统,看起来像这样的一张桌子。将字符串变成行

OptionsTable 
id options 
=== ======================== 
101 Apple,Banana    
102 Audi,Mercedes,Volkswagen 

在消耗数据,功能会分解选项列进名单管理和填充下拉列表等应用

的问题是,这种数据不是很友好SQL,使得难以进行临时查询和报告。

为此,我想将数据转换成一个友好的观点,看起来像这样:

OptionsView 
id name  value 
=== ========== ===== 
101 Apple   1 
101 Banana   2 
102 Audi   1 
102 Mercedes  2 
102 Volkswagen  3 

现在,已经有上分割字符串一些议题到在T-SQL行(Turning a Comma Separated string into individual rows想到),但除了将字符串拆分为行之外,我还需要根据字符串中的位置生成值。

该计划是制作隐藏原始表的uglines的视图。

它将与表中的答案一起用于收集答案,以便进行临时统计查询。

有没有这样做的好方法,而不必使用游标等?

回答

0

也许增加一个udf是为你的需要矫枉过正,但我​​很久以前创建了一个split函数,它返回值,字符串中的开始位置和索引。有了它,在这种情况下的用法是:

select id, String as [Name], ItemIndex as value from OptionsTable 
outer apply dbo.Split(options, ',') 

结果:

id Name value 
101 Apple 1 
101 Banana 2 
102 Audi 1 
102 Mercedes 2 
102 Volkswagen 3 

和分割功能(自那时以来未修订):

ALTER function [dbo].[Split] ( 
@StringToSplit varchar(2048), 
@Separator varchar(128)) 
returns table as return 

with indices as 
( 
select 0 S, 1 E, 0 I 
union all 
select E, charindex(@Separator, @StringToSplit, E) + len(@Separator) , I + 1 
from indices 
where E > S 
) 
select substring(@StringToSplit,S, 
case when E > len(@Separator) then e-s-len(@Separator) else len(@StringToSplit) - s + 1 end) String 
,S StartIndex, I ItemIndex   
from indices where S >0 
0

这应该为你工作:

DECLARE @OptionsTable TABLE 
(
    id INT 
    , options VARCHAR(100) 
); 

INSERT INTO @OptionsTable (id, options) 
VALUES (101, 'Apple,Banana') 
    , (102, 'Audi,Mercedes,Volkswagen'); 

SELECT OT.id, T.name, t.value 
FROM @OptionsTable AS OT 
CROSS APPLY (
    SELECT T.column1, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
    FROM dbo.GetTableFromList(OT.options, ',') AS T 
    ) AS T(name, value); 

Here dbo.GetTableFromList是一个拆分字符串函数。
CROSS APPLY对每行执行此函数,从而导致将选项拆分为单独行中的名称。而我用ROW_NUMBER()加值行,如果要按名称命名结果集,请使用ROW_NUMBER() OVER (ORDER BY t.column1),这应该和可能会使结果一直保持一致。

结果:

id name value 
----------------- 
101 Apple  1 
101 Banana  2 
102 Audi  1 
102 Mercedes 2 
102 Volkswagen 3 
0

则可以将字符串转换为XML,然后解析字符串将其移至行是这样的:

SELECT A.[id] 
     ,Split.a.value('.', 'VARCHAR(100)') AS Name 
     ,ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY (SELECT NULL)) as Value 
FROM (
    SELECT [id] 
     ,CAST('<M>' + REPLACE([options], ',', '</M><M>') + '</M>' AS XML) AS Name 
    FROM optionstable 
    ) AS A 
CROSS APPLY Name.nodes('/M') AS Split(a); 

现金@SRIRAM

SQL Fiddle Demo

+0

使用XML拆分字符串方法是相当危险的。“一个非常强烈的警告必须与XML方法一起使用:只有在您可以保证您的输入字符串不包含任何非法XML字符时才能使用它。一个名字<, >或者&功能会炸毁'。如本文中所述http://sqlperformance.com/2012/07/t-sql-queries/split-strings –