我在
下面有一个输入表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
答案 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
答案 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