我们首先先通过一个老生常谈的例子,学生成绩表(下面简化了些)来形象了解下行转列
如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成一行,这样方便我查看、统计,导出数据
接下来我们来看看第二个小列子。有一个游戏玩家充值表(仅仅为了说明,举的一个小例子),
代码
如图所示,我们这样只是得到了这样的输出结果,还需进一步处理,才能得到想要的结果
其实行转列,关键是要理清逻辑,而且对分组(Group by)概念比较清晰。上面两个列子基本上就是行转列的类型了。但是有个问题来了,上面是我为了说明弄的一个简单列子。实际中,可能支付方式特别多,而且逻辑也复杂很多,可能涉及汇率、手续费等等(曾经做个这样一个),如果支付方式特别多,我们的CASE WHEN 会弄出一大堆,确实比较恼火,而且新增一种支付方式,我们还得修改脚本如果把上面的脚本用动态SQL改写一下,我们就能轻松解决这个问题
下面是通过PIVOT来进行行转列的用法,大家可以对比一下,确实要简单、更具可读性(呵呵,习惯的前提下)
有时可能会出现这样的错误:
消息 325,级别 15,状态 1,第 9 行
'PIVOT' 附近有语法错误。您可能需要将当前数据库的兼容级别设置为更高的值,以启用此功能。有关存储过程 sp_dbcmptlevel 的信息,请参见帮助。
这个是因为:对升级到 SQL Server 2005 或更高版本的数据库使用 PIVOT 和 UNPIVOT 时,必须将数据库的兼容级别设置为 90 或更高。有关如何设置数据库兼容级别的信息,请参阅 sp_dbcmptlevel (Transact-SQL)。 例如,只需在执行上面脚本前加上 EXEC sp_dbcmptlevel Test, 90; 就OK了, Test 是所在数据库的名称。
下面我们来看看列转行,主要是通过UNION ALL ,MAX来实现。假如有下面这么一个表
我们可以通过下面的脚本来实现,查询结果如下图所示
用UNPIVOT 实现如下:
===================================================行转列============
===================================================行转列============
Connected to Oracle9i Enterprise Edition Release 9.2.0.1.0 Connected as SYSSQL> create table t1("group" number(2),c1 number(2),c2 number(2),c3 number(2),c4 number(2));Table createdSQL> SQL> insert into t1 values(1,11,12,13,14);1 row insertedSQL> insert into t1 values(2,21,22,23,24);1 row insertedSQL> insert into t1 values(3,31,32,33,34);1 row insertedSQL> select * from t1;group C1 C2 C3 C4----- --- --- --- --- 1 11 12 13 14 2 21 22 23 24 3 31 32 33 34SQL> SQL> select "group",c1 c from t1 union all select "group",c2 c from t1 union all select "group",c3 c from t1 union all select "group",c4 c from t1 order by "group"; group C---------- ---------- 1 11 1 12 1 13 1 14 2 21 2 23 2 24 2 22 3 31 3 34 3 33 3 3212 rows selectedSQL>===================================================列转行============
SQL> create table t2 as select "group",c1 c from t1 union all select "group",c2 c from t1 union all select "group",c3 c from t1 union all select "group",c4 c from t1 order by "group";Table createdSQL> select * from t2;group C----- --- 1 11 1 12 1 13 1 14 2 21 2 23 2 24 2 22 3 31 3 34 3 33 3 3212 rows selectedSQL> SQL> SELECT "group", MAX(decode(rn, 1, c, NULL)) AS c1, MAX(decode(rn, 2, c, NULL)) AS c2, MAX(decode(rn, 3, c, NULL)) AS c3, MAX(decode(rn, 4, c, NULL)) AS c4 FROM ( select "group",c,row_number()over(partition by "group" order by "group") rn from t2 ) GROUP BY "group" ORDER BY 1;group C1 C2 C3 C4----- ---------- ---------- ---------- ---------- 1 11 12 13 14 2 21 23 24 22 3 31 34 33 32