将分隔符拆分为多列

时间:2017-09-14 11:03:19

标签: sql sql-server sql-server-2012

我有一张20列的桌子。其中一列包含由分号分隔的多个值。它看起来像这样:

-9;-9;-1;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-1;-1;-1;-1;-9;-1;-1;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-1;-9;-9;-1;-1;-9;-1;-1;0000;FFF8;-9;-9;-9;-1;-9;-1;-9;FFF6;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9

它始终包含115个值。值可以是" -1"," -9"或十六进制数。

现在我想创建一个视图,其中包含原始的20列加上115列foreach分隔的字符串。有人能帮助我吗?

3 个答案:

答案 0 :(得分:3)

这是一个如何执行此操作的示例:

DECLARE @tt TABLE(i INT IDENTITY,x VARCHAR(8000));
INSERT INTO @tt(x)VALUES('-9;-9;-1;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-1;-1;-1;-1;-9;-1;-1;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-1;-9;-9;-1;-1;-9;-1;-1;0000;FFF8;-9;-9;-9;-1;-9;-1;-9;FFF6;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9');

SELECT
    i,
    val1=n.v.value('/e[1]','VARCHAR(16)'),
    val2=n.v.value('/e[2]','VARCHAR(16)'),
    val3=n.v.value('/e[3]','VARCHAR(16)'),
    -- ... repeat for val4 .. val114
    val115=n.v.value('/e[115]','VARCHAR(16)')
FROM
    @tt
    CROSS APPLY (
        SELECT 
            CAST('<e>'+REPLACE(x,';','</e><e>')+'</e>' AS XML) AS itm
    ) AS i
    CROSS APPLY i.itm.nodes('/') AS n(v);

这是一些XML技巧,通过将带有分隔值的列设为XML,其中每个值都是e元素。然后使用value函数中的索引检索单个元素。

由于这是单个语句,因此可以在视图中用作查询。

答案 1 :(得分:2)

您可以使用返回位置的拆分功能。不幸的是,SQL Server 2016中的split_string()尚不支持此功能。 (Microsoft is aware of this.

您可以找到此类功能的代码(例如,here,但我不建议使用该特定版本。)

然后你可以这样做:

select t.*, v.*
from t cross apply
     (select max(case when pos = 1 then val end) as col_001,
             max(case when pos = 2 then val end) as col_002,
             . . .
             max(case when pos = 115 then val end) as col_115
      from dbo.split(';', t.col) s(pos, val)
     ) v;

答案 2 :(得分:0)

您可以查询如下:

Declare @cols2 varchar(max)
Declare @query nvarchar(max)

--Row Numbers with tally
;with c1 as (
    Select top(Select max(len(splitcolumn) - len(replace(splitcolumn,';',''))) from #data) 
        RowN = Row_number() over (order by (Select NULL))
    from master..spt_values s1, master..spt_values 
)
select @cols2 = stuff((select ','+QuoteName(RowN) from c1 group by RowN for xml path('')),1,1,'')

Select @query = '
    Select * from (
        Select Id, RowN, [Value] from #data
        cross apply (
                Select xm = CAST(''<x>'' + REPLACE((SELECT REPLACE(splitcolumn,'';'',''$$$SSText$$$'') AS [*] FOR XML PATH('''')),''$$$SSText$$$'',''</x><x>'')+ ''</x>'' AS XML) 
        ) a
        cross apply (
            Select RowN = Row_Number() over (order by (SELECT NULL)), y.value(N''text()[1]'', N''nvarchar(MAX)'') as value 
            FROM a.xm.nodes(N''x'') as x(y) 
        ) b
    ) rws
    pivot (max([Value]) for RowN in (' + @cols2 + ')) p'

Exec sp_executesql @query
相关问题