拆分数据并将其转换为列

时间:2015-10-08 07:07:17

标签: sql-server tsql pivot sql-server-2014

我在

下面有一个输入表
Id  Data
1   Column1: Value1
2   Column2: Value11
3   Column3: Value111
4   Column1: Value2
5   Column2: Value22
6   Column3: Value222

我正在寻找

下的输出
Column1      Column2    Column3
Value1       Value11    Value111
Value2       Value22    Value222

我怎么能这样做?它可以通过使用WHILE LOOP和一些数学逻辑轻松完成,但如果可能的话,我只想通过SELECT查询(没有LOOPS)来寻找更优化的一个。

我也试过将(':')拆分为分隔符,然后将ROWS转换为COLUMNS(PIVOT),但有些无法继续。 (这是我的想法,人们可能有更好的想法)。

到目前为止我的镜头

Declare @t table(Id int identity(1,1),Data varchar(1000))
Insert into @t Values
    ('Column1: Value1'),('Column2: Value11'),('Column3: Value111')
    ,('Column1: Value2'),('Column2: Value22'),('Column3: Value222')

Select *
FROM @t
SELECT 
 F1.id,
 F1.Data,
 O.splitdata 
FROM
 (
 SELECT *,
 cast('<X>'+replace(F.Data,':','</X><X>')+'</X>' as XML) as xmlfilter from @t F
 )F1
 CROSS APPLY
 ( 
 SELECT fdata.D.value('.','varchar(50)') as splitdata 
 FROM f1.xmlfilter.nodes('X') as fdata(D)) O

2 个答案:

答案 0 :(得分:2)

如果您需要纯SQL解决方案,这将有效:

+3 days

但是它假设第1行的数据总是在第2行的数据之前。没有办法用你的样本来区分它们。

如果列数不固定,则必须使用动态SQL。

SQL Server可能不是此类事情的最佳选择。

使用Dynamic SQL,上面的查询就像这样:

Select [Column1], [Column2], [Column3] From (
    Select col, val, id = ROW_NUMBER() over(partition by d.col order by d.id)
    From (
         Select id
            , col = LEFT(Data, CHARINDEX(':', Data)-1)
            , val = RIGHT(Data, LEN(DATA) - CHARINDEX(':', Data))

         From @t
    ) as d
) as p
pivot(
    MAX(val)
    FOR col in([Column1], [Column2], [Column3])
) as piv

SQL Fiddle

答案 1 :(得分:1)

这应该有效:

Declare @t table(Id int identity(1,1),Data varchar(1000))
Insert into @t Values
    ('Column1: Value1'),('Column2: Value11'),('Column3: Value111')
    ,('Column1: Value2'),('Column2: Value22'),('Column3: Value222');

WITH Splitted AS
(
     SELECT *
           ,CAST('<X>'+REPLACE(F.Data,':','</X><X>')+'</X>' AS XML) AS xmlfilter 
     FROM @t AS F
)
SELECT p.*
FROM
(
    SELECT ROW_NUMBER() OVER(PARTITION BY xmlfilter.value('X[1]','varchar(max)') ORDER BY Id) AS Inx 
          ,xmlfilter.value('X[1]','varchar(max)') AS ColName
          ,xmlfilter.value('X[2]','varchar(max)') AS ColVal
    FROM Splitted
) AS tbl
PIVOT
(
    MAX(ColVal) FOR ColName IN(Column1,Column2,Column3)
) AS p