4

假设我有这张桌子:

Create table test(a int, b int, c int, d int)

我可以简单地写'select * from test'来获得以下第一条记录:

A B C D  
1 2 3 4

但相反,我想要这样(单条记录四行):

答:1  
乙:2  
C: 3  
D: 4

有人可以帮我这样做吗?

这是在远程桌面系统上查看单个记录所必需的,该系统非常慢,并且水平滚动很糟糕,其中有 800 列。所以我需要从一条记录中查看数据的格式。

4

1 回答 1

11

您可以使用该UNPIVOT函数来执行此操作,以下版本将列名和值连接在一起,但您始终可以将它们显示为单独的列:

select col+':'+cast(value as varchar(10)) col
from test
unpivot
(
  value
  for col in (A, B, C, D)
) unpiv

请参阅带有演示的 SQL Fiddle

如果您有已知数量的列,上述方法非常有用,但如果您有 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

注意:使用时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, '')

第二部分获得相同的列列表,但将每一列包装在 acastvarchar

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

UNPIVOT函数正在执行与 a 相同的过程,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

所有查询的结果都是一样的:

|    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

替换空值,将得到如下结果:

|    COL |
----------
|    A:1 |
| B:2.00 |
|     C: |
|    D:4 |
于 2012-12-12T13:07:09.667 回答