用于获取格式为 "column heading: column value"的单个记录的 SQL 查询

标签 sql sql-server sql-server-2008 tsql unpivot

假设我有这张表:

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

我可以简单地编写“select * from test”来获取以下第一条记录:

A    B    C    D  
1    2    3    4

但是,我想要这样的(单个记录四行):

A: 1  
B: 2  
C: 3  
D: 4

有人可以帮我做这件事吗?

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

最佳答案

您可以使用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 |

关于用于获取格式为 "column heading: column value"的单个记录的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13840468/

相关文章:

c# - .NET 和 T-SQL 之间的字符串比较差异?

sql - 如何在存储过程中创建索引?

mysql - SQL Server 迁移到 mySQL、提示和潜在问题?

php - 找到表名,然后从该表中获取数据。

mysql - SQL 语法错误 INSERT INTO

sql-server - silverlight 5 功能请求列表?

sql-server - 如何在 XML PATH 查询上创建 View 或函数?

c# - 使用 CLR 存储过程时遇到的问题和解决方法?

java - 从字符串到 Clob 以及 Clob 到字符串的转换

SQL 加入 ID 和日期