您可以使用UNPIVOT 函数来执行此操作,以下版本将列名和值连接在一起,但您始终可以将它们显示为单独的列:
select col+':'+cast(value as varchar(10)) col
from test
unpivot
(
value
for col in (A, B, C, D)
) unpiv
见SQL Fiddle with Demo
如果您有已知数量的列,上述方法非常有用,但如果您有 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)
见SQL Fiddle with Demo
注意:当使用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, '')
第二部分获得相同的列列表,但将每一列包装在 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, '')
那么您的最终查询将是:
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)
见SQL Fiddle with Demo
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
见SQL Fiddle with Demo
所有查询的结果都是一样的:
| COL |
----------
| A:1 |
| B:2.00 |
| C:3 |
| D:4 |
编辑 #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)
见SQL Fiddle with Demo
替换空值,将得到如下结果:
| COL |
----------
| A:1 |
| B:2.00 |
| C: |
| D:4 |