tee*_*nup 4 sql t-sql sql-server unpivot sql-server-2008
假设我有这个表:
Create table test(a int, b int, c int, d int)
Run Code Online (Sandbox Code Playgroud)
我可以简单地写'select*from test'来获得以下第一条记录:
A B C D 1 2 3 4
但相反,我希望它像这样(单行记录四行):
A: 1 B: 2 C: 3 D: 4
有人可以帮我这么做吗?
这是查看远程桌面系统上的单个记录所必需的,该记录非常慢,并且在其上水平滚动很糟糕,并且其中有800列.所以我需要从单个记录中看到数据的格式.
Tar*_*ryn 11
您可以使用该UNPIVOT函数执行此操作,下面的版本将列名称和值连接在一起,但您始终可以将它们显示为单独的列:
select col+':'+cast(value as varchar(10)) col
from test
unpivot
(
value
for col in (A, B, C, D)
) unpiv
Run Code Online (Sandbox Code Playgroud)
如果您具有已知数量的列,则上述工作非常有用,但如果您要转换800个列,则可能需要使用动态sql执行此操作:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
set @query
= 'select col+'':''+cast(value as varchar(10)) col
from test
unpivot
(
value
for col in ('+ @colsunpivot +')
) u'
exec(@query)
Run Code Online (Sandbox Code Playgroud)
注意:使用UNPIVOT所有需要转换的列的数据类型时,必须相同.因此,您可能需要根据需要转换/转换数据.
编辑#1,因为您的所有列上的数据类型不同,并且您需要取消它们,然后您可以使用以下代码.
第一部分获取要动态展开的列的列表:
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
Run Code Online (Sandbox Code Playgroud)
第二部分获取相同的列列表,但将每列包装cast为varchar:
select @colsUnpivotCast = stuff((select ', cast('+quotename(C.name)+' as varchar(50)) as '+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
Run Code Online (Sandbox Code Playgroud)
然后你的最终查询将是:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@colsUnpivotCast AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
select @colsUnpivotCast = stuff((select ', cast('+quotename(C.name)+' as varchar(50)) as '+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
set @query
= 'select col+'':''+value col
from
(
select '+@colsUnpivotCast+'
from test
) src
unpivot
(
value
for col in ('+ @colsunpivot +')
) u'
exec(@query)
Run Code Online (Sandbox Code Playgroud)
该UNPIVOT函数执行的过程与UNION ALL看起来像这样:
select col+':'+value as col
from
(
select A value, 'A' col
from test
union all
select cast(B as varchar(10)) value, 'B' col
from test
union all
select cast(C as varchar(10)) value, 'C' col
from test
union all
select cast(D as varchar(10)) value, 'D' col
from test
) src
Run Code Online (Sandbox Code Playgroud)
所有查询的结果都是相同的:
| COL |
----------
| A:1 |
| B:2.00 |
| C:3 |
| D:4 |
Run Code Online (Sandbox Code Playgroud)
编辑#2:使用UNPIVOT剥离任何可能导致某些数据丢失的空列.如果是这种情况,那么您将要包含列IsNull()以替换null值:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@colsUnpivotCast AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
select @colsUnpivotCast = stuff((select ', IsNull(cast('+quotename(C.name)+' as varchar(50)), '''') as '+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('test')
for xml path('')), 1, 1, '')
set @query
= 'select col+'':''+value col
from
(
select '+@colsUnpivotCast+'
from test
) src
unpivot
(
value
for col in ('+ @colsunpivot +')
) u'
exec(@query)
Run Code Online (Sandbox Code Playgroud)
替换空值将得到如下结果:
| COL |
----------
| A:1 |
| B:2.00 |
| C: |
| D:4 |
Run Code Online (Sandbox Code Playgroud)