天天看点

DECODE函数实现列转行

在实际的开发当中有时候会有让你做统计、做报表。

比如在学生选课管理系统中让你写出所有的学生的每一门可的成绩,这时候我们写的SQL得出的结果一般是每一个学生选了好多课,其中每一个课和对应的成绩都是一行记录。

如下格式:

NAME COURSE GREAD
---- ------ -----
dai  java      60
dai  c#	       70
dai  c	       80
dai  sql       90
           

往往上面的格式不是我们想要的,我们想要的格式像如下所示:

NAME JAVA C# C  SQL
---- ---- -- -- ---
dai	   60 70 80  90
           

下面我们就构造一个完整的示例来看看上面的情况要如何实现:

CREATE TABLE t(
        name VARCHAR2(10),
        course VARCHAR2(10),
        gread NUMBER
)

BEGIN
	INSERT INTO t VALUES('dai', 'java', 60);
	INSERT INTO t VALUES('dai', 'c#', 70);
	INSERT INTO t VALUES('dai', 'c', 80);
	INSERT INTO t VALUES('dai', 'sql', 90);
	INSERT INTO t VALUES('tu', 'java', 90);
	INSERT INTO t VALUES('tu', 'c#', 80);
	INSERT INTO t VALUES('tu', 'c', 70);
	INSERT INTO t VALUES('tu', 'sql', 60);
END;
           

以上的代码构造好了数据。

下面我们分成两部来实现学生的成绩报表:

1、通过使用DECODE实现行列转换,查询出每个学生选的课程和相应的成绩。

SELECT name,
	DECODE(course, 'java', gread) AS java,
	DECODE(course, 'c#', gread) AS c#,
	DECODE(course, 'c', gread) AS c,
	DECODE(course, 'sql', gread) AS sql
FROM t;
NAME             JAVA         C#          C        SQL
---------- ---------- ---------- ---------- ----------
dai                60
dai                           70
dai                                      80
dai                                                 90
tu                 90
tu                            80
tu                                       70
tu                                                  60
           

2、通过使用聚合函数MAX()来实现化散为整

通过第一步的结果,我们发现使用DECODE构造出了由course字段组成了行,但是我们发现每一个课程和相应的成绩还是出现一行。但是你仔细观察,是不是只要将同一姓名的每一行往上压缩一下,就变成了一行了。那我们要怎么做到嘞?在这里我们应该想到使用分组(GROUP BY)来实现。

SELECT name,
        MAX(DECODE(course, 'java', gread)) AS java,
        MAX(DECODE(course, 'c#', gread)) AS c#,
        MAX(DECODE(course, 'c', gread)) AS c,
        MAX(DECODE(course, 'sql', gread)) AS sql
FROM t
GROUP BY name;

NAME             JAVA         C#          C        SQL
---------- ---------- ---------- ---------- ----------
dai                60         70         80         90
tu                 90         80         70         60
           

看得到我们想要的结果了吧。

现在不是流行说"那么,问题就来了!"这句话么。的确!对于细心的人来说那么问题就来了。

在这里我们为什么要使用MAX()而不使用SUM()、AVG()等等聚合函数?告诉大家其实在示例中确实上面3个聚合函数都能使用并且都能成功实现。但是如果在聚合函数里面的值是 字符型的使用SUM()、AVG()还行么?答案是不行了,所以使用MAX()也算是一种兼容的考虑的。