我有一个动态生成的表,我需要将所有列都更改为行
所以我的表看起来像这样
Conv1 | Conv2 | ...
data1 | data2 | ...
data1 | data2 | ...
data1 | data2 | ...
... | ... | ...
因为它的动态我不知道有多少行/列没有运行Select count(*)
或类似的东西。
基本上我希望将上面的表格改为此
data1 | data1 | data1 | ...
data2 | data2 | data2 | ...
data3 | data3 | data3 | ...
data4 | data4 | data4 | ...
我查看了使用Pivot
,但我不确定在这种情况下我会如何使用它。
我正在使用SQL Server 2008 R2
任何帮助将不胜感激。如果您需要更多信息,请与我们联系。
谢谢。
- 更新
这里是" Conv"的当前表格结构。项目作为列名。
Conv1 | Conv2 | Conv3 | ...
data1 | data2 | data3 | ...
data1 | data2 | data3 | ...
data1 | data2 | data3 | ...
... | ... | ... | ...
其中"数据"件是varchar(250)
将数据视为会话存储库(Conv1),行是一系列问题和响应。 因为我必须与之合作的性质,我不知道哪个"数据"内容是一个问题,也是一种回应。
这就是我想要的结果:
Col1 | Col2 | Col3 | ...
Conv1 | data1 | data1 | data1 | ...
Conv2 | data2 | data2 | data2 | ...
Conv3 | data3 | data3 | data3 | ...
Conv4 | data4 | data4 | data4 | ...
如果仍然没有足够的信息让我知道,我会看到我还能提供什么。
答案 0 :(得分:1)
您要做的是完整的数据转置,其中您当前的数据列成为行,而您的行成为列,这可以通过两个步骤完成。首先,应用UNPIVOT函数将当前Conv1
,Conv2
等列转换为行,然后应用PIVOT函数将data1
,data2
转换为列
在尝试编写查询的动态版本之前,我总是从静态版本开始,因此可以获得正确的逻辑,然后转换为动态sql。为了生成新的列名Col1
,Col2
等,我会在查询数据时使用像row_number()
这样的窗口函数,这将为每行数据生成一个唯一的序列你想要转置。
UNPIVOT代码类似于:
;with cte as
(
select Conv1, Conv2, Conv3,
row_number() over(order by conv1) seq
from dbo.yourtable
)
select *
from
(
select Conv, value,
col = 'Col'+cast(seq as varchar(50))
from cte
unpivot
(
value for Conv in (Conv1, Conv2, Conv3)
) unpiv
) src;
见SQL Fiddle with Demo。数据看起来像:
| CONV | VALUE | COL |
|-------|-------|------|
| Conv1 | data1 | Col1 |
| Conv2 | data2 | Col1 |
| Conv3 | data3 | Col1 |
| Conv1 | data1 | Col2 |
| Conv2 | data2 | Col2 |
| Conv3 | data3 | Col2 |
您现在已经注意到,每个Conv1
都有多行,并且您有一个新列,使用row_number()
创建新的列名。现在您可以使用PIVOT完成数据的旋转:
;with cte as
(
select Conv1, Conv2, Conv3,
row_number() over(order by conv1) seq
from dbo.yourtable
)
select Conv, Col1, Col2, Col3
from
(
select Conv, value,
col = 'Col'+cast(seq as varchar(50))
from cte
unpivot
(
value for Conv in (Conv1, Conv2, Conv3)
) unpiv
) src
pivot
(
max(value)
for col in (Col1, Col2, Col3)
) piv;
见SQL Fiddle with Demo。这将完全将您当前的数据转换为最终结果。对于您的情况,您声明需要动态解决方案,因此您需要使用动态SQL。这将涉及获取需要忽略的列名列表,然后是枢轴的新列:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@colsPivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsUnpivot = STUFF((SELECT ','+ quotename(c.name)
from sys.tables t
inner join sys.columns c
on t.object_id = c.object_id
where t.name = 'yourtable'
group by c.name, c.column_id
order by c.column_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @colsPivot = STUFF((SELECT ','+ quotename('Col'+cast(seq as varchar(10)))
from
(
select row_number() over(order by conv1) seq
from dbo.yourtable
) d
group by seq
order by seq
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= ';with cte as
(
select Conv1, Conv2, Conv3,
row_number() over(order by conv1) seq
from dbo.yourtable
)
select Conv, '+@colsPivot+'
from
(
select Conv, value,
col = ''Col''+cast(seq as varchar(50))
from cte
unpivot
(
value for Conv in ('+@colsUnpivot+')
) unpiv
) src
pivot
(
max(value)
for col in ('+@colsPivot+')
) piv'
execute sp_executesql @query;
见SQL Fiddle with Demo。两者都给出了最终结果:
| CONV | COL1 | COL2 | COL3 |
|-------|-------|-------|-------|
| Conv1 | data1 | data1 | data1 |
| Conv2 | data2 | data2 | data2 |
| Conv3 | data3 | data3 | data3 |