将列转置为行 SQL Server

Posted

技术标签:

【中文标题】将列转置为行 SQL Server【英文标题】:Transpose columns to rows SQL Server 【发布时间】:2015-08-28 16:37:35 【问题描述】:

如果我要转换为行的列都以列名中的前缀“c”开头,如何将某些列动态转置为行。我有一张如下表

DECLARE @t codes 
(
  Tax CHAR(5),
  ptype CHAR(2),
  c1 CHAR(1),
  c2 char(1),
  c3 char(1)
)

insert into @t (tax, ptype, c1, c2, c3) values ('AAAAA','10',Null, 1,2)
insert into @t (tax, ptype, c1, c2, c3) values ('BBBBB','21',3, 1,NULL)
insert into @t (tax, ptype, c1, c2, c3) values ('ZZZZZ','1',NULL, NULL, 2)
insert into @t (tax, ptype, c1, c2, c3) values ('CCCCC',NULL,1,3,4)
insert into @t (tax, ptype, c1, c2, c3) values ('YYYYY','4',NULL, NULL, NULL)
insert into @t (tax, ptype, c1, c2, c3) values ('DDDDD','8',2,5,6)

当 ptype 不是 'NULL' 以及 c1、c2、c3 不是 'NULL' 且 C1、C2、C3 值按升序排序时,如何输出以下内容?

Tax   ptype  Columns value
----- -----  ------- -----
AAAAA 10     c2      1
AAAAA 10     c3      2 
BBBBB 21     c2      1
BBBBB 21     c1      3 
ZZZZZ 1      c3      2
DDDDD 8      c1      2 
DDDDD 8      c2      5
DDDDD 8      c3      6

【问题讨论】:

你的输出一点都不清楚。你想要文字值'C2'等吗?如果你能清楚地解释你的输出,我们可以提供帮助。 @SeanLange 我想要“列”中的列名。我将编辑 OP 以澄清。谢谢 【参考方案1】:

查询

SELECT Tax 
      ,ptype
      ,[Columns]
      ,Value 
   FROM @t
     UNPIVOT (Value FOR Columns IN ( C1 , C2 , C3 ))up 

结果集

╔═══════╦═══════╦═════════╦═══════╗
║  Tax  ║ ptype ║ Columns ║ Value ║
╠═══════╬═══════╬═════════╬═══════╣
║ AAAAA ║ 10    ║ c2      ║     1 ║
║ AAAAA ║ 10    ║ c3      ║     2 ║
║ BBBBB ║ 21    ║ c1      ║     3 ║
║ BBBBB ║ 21    ║ c2      ║     1 ║
║ ZZZZZ ║ 1     ║ c3      ║     2 ║
║ CCCCC ║ NULL  ║ c1      ║     1 ║
║ CCCCC ║ NULL  ║ c2      ║     3 ║
║ CCCCC ║ NULL  ║ c3      ║     4 ║
║ DDDDD ║ 8     ║ c1      ║     2 ║
║ DDDDD ║ 8     ║ c2      ║     5 ║
║ DDDDD ║ 8     ║ c3      ║     6 ║
╚═══════╩═══════╩═════════╩═══════╝

如果你想从结果集中消除空值,只需在上面的查询中添加 where 子句

WHERE [Columname] IS NOT NULL

【讨论】:

【参考方案2】:

我将使用CROSS APPLYtable valued constructor 来反透视数据

SELECT tax, 
       ptype, 
       columns, 
       value 
FROM   @t 
       CROSS apply (Select 'c1',c1 
                    UNION ALL 
                    Select 'c2',c2 
                    UNION ALL
                    Select 'c3',c3 ) cs(columns, value) 
WHERE  ptype IS NOT NULL 
       AND columns IS NOT NULL 
       AND value IS NOT NULL 

SQL FIDDLE DEMO

【讨论】:

感谢@Indian,但我使用的是 SQL 服务 2005,我相信 CROSS 应用不起作用 @user176047 交叉应用是在 2005 年引入的,因此只要您的数据库兼容性级别设置为 90,它就应该可以工作。 @user176047 - 阿里是正确的。 Cross apply 是 2005 年引入的。但问题是 table valued constructor 是 2008 年引入的。现在更新了代码检查。这就是为什么您应该为您的问题添加适当的标签 我发现使用 UNPIVOT 更容易做到这一点,因为语法是针对这种情况引入的;)

以上是关于将列转置为行 SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

oracle sql 11G中如何将列转置为行

使用交叉应用将列转置为行

使用 Spark 将列转置为行

Oracle:将列转置为行

Postgresql 查询将列转置为行

Postgres 表选择多列并将结果(列)动态转换为行 - 将列转置为行