您的位置:首页 > 数据库 > Oracle

Oracle 行转列

2015-06-23 11:03 429 查看
-- 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: