Oracle 行转列

-- Start

在网上看到这样一个问题.

班级 科目 分数
1    语文 8800
1    数学 8420
1    英语 7812
2    语文 8715
2    数学 8511
2    英语 8512

要求转换成下面这样的结果.

班级 语文  数学  英语
1    8800  8420 7812
2    8715  8511 8512

这是一个非常经典的 4 属性的表设计模式,顾名思义,这样的表一般有四列,分别是:entity_id, attribute_name, attribute_type, attribute_value ,这样的设计使我们添加字段非常容易,如:我们想添加一个物理成绩是非常简单的,我们只要向表中插入一条记录即可。但是,这样的设计有一个非常严重的问题,那就是:查询难度增加,查询效率非常差。要想实现上面的查询有一个原则,那就是:通过 case 语句创造虚拟字段,使结果集成为二维数组,然后应用聚合函数返回单一记录。怎么样?不理解,仔细看看下面的图和分析下面的语句你就理解了。


create table entity
(
	entity_id       number(9,0),
	attribute_name  varchar2(10),
	attribute_type  varchar2(10),
	attribute_value varchar2(10)
);

insert into entity values (1, 'Chinese', 'NUMBER', '8800');
insert into entity values (1, 'Math',    'NUMBER', '8420');
insert into entity values (1, 'English', 'NUMBER', '7812');
insert into entity values (2, 'Chinese', 'NUMBER', '8715');
insert into entity values (2, 'Math',    'NUMBER', '8511');
insert into entity values (2, 'English', 'NUMBER', '8512');

select
	Class,
	max(Chinese)  Chinese,
	max(Math)     Math,
	max(English) English
from (
	select 
		entity_id class,
		case attribute_name when 'Chinese' then to_number(attribute_value) else 0 end Chinese,
		case attribute_name when 'Math'    then to_number(attribute_value) else 0 end Math,
		case attribute_name when 'English' then to_number(attribute_value) else 0 end English
	from entity
) tt
group by tt.class
order by 1;

你可能正在感叹,这样的解决方案是多么的巧妙,可惜不是我想出来的,在这里,我也不敢把大师的思想据为己有,以上思想来自<SQL 语言艺术>的第11 章,想了解更全面的信息,大家可以参考。

-- 更多参见:Oracle SQL 精萃

-- 声明:转载请注明出处

-- Last edited on 2015-06-23

-- Created by ShangBo on 2015-06-23

-- End


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值