-- 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