一、行转列
主要原理是利用decode函数、聚集函数(sum),结合group by分组实现的
例:
--查看表是否存在
select * from T_TEST_GRADE T;
--新建测试表
create table T_TEST_GRADE
(
GRADE_ID VARCHAR2(10) not null,
USER_NAME VARCHAR2(20),
COURSE VARCHAR2(20),
SCORE VARCHAR2(3)
);
--插入测试数据
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('1','james','english','65');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('2','james','basketball','95');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('3','james','math','75');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('4','hardon','english','75');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('5','hardon','basketball','85');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('6','hardon','math','65');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('7','durant','english','76');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('8','durant','basketball','90');
INSERT INTO T_TEST_GRADE(GRADE_ID,USER_NAME,COURSE,SCORE) VALUES ('9','durant','math','75');
--利用decode和group by进行行转列
select t.user_name,
sum(decode(t.course, 'english', score, null)) as 英语,
sum(decode(t.course, 'basketball', score, null)) as 篮球,
sum(decode(t.course, 'math', score, null)) as 数学
from t_test_grade t
group by t.user_name
order by t.user_name;
如果要实现对各门功课的不同分数段进行统计
效果如下:
分数段 英语 篮球 数学
60-80 3 0 3
80-100 0 3 0
相应的sql如下,最终还是行转列:
select t2.分数段,
sum(decode(t2.course, 'english', COUNTNUM, 0)) as 英语,
sum(decode(t2.course, 'basketball', COUNTNUM, 0)) as 篮球,
sum(decode(t2.course, 'math', COUNTNUM, 0)) as 数学
from (select t.course,
case
when t.score < 60 then
'00-60'
when t.score >= 60 and t.score < 80 then
'60-80'
when t.score >= 80 then
'80-100'
end as 分数段,
count(t.score) as COUNTNUM
FROM t_test_grade t
group by t.course,
case
when t.score < 60 then
'00-60'
when t.score >= 60 and t.score < 80 then
'60-80'
when t.score >= 80 then
'80-100'
end
order by t.course) t2
group by t2.分数段
order by t2.分数段;
二、列转行
主要原理是利用SQL里面的union,也可以利用【 insert all into ... select 】来实现,insert all into...select需要额外新建临时表
例:
select * from T_TEST_GRADE2 T;
create table T_TEST_GRADE2
(
GRADE_ID NUMBER(10) not null,
USER_NAME VARCHAR2(20),
ENGLISH_SCORE VARCHAR2(3),
BASKETBALL_SCORE VARCHAR2(3),
MATH_SCORE VARCHAR2(3)
);
INSERT INTO T_TEST_GRADE2(GRADE_ID,USER_NAME,ENGLISH_SCORE,BASKETBALL_SCORE,MATH_SCORE) VALUES ('1','james','65','95','75');
INSERT INTO T_TEST_GRADE2(GRADE_ID,USER_NAME,ENGLISH_SCORE,BASKETBALL_SCORE,MATH_SCORE) VALUES ('2','hardon','75','85','65');
INSERT INTO T_TEST_GRADE2(GRADE_ID,USER_NAME,ENGLISH_SCORE,BASKETBALL_SCORE,MATH_SCORE) VALUES ('3','durant','76','90','75');
select user_name, '英语' COURSE, english_score as SCORE
from t_test_grade2
union
select user_name, '篮球' COURSE, basketball_score as SCORE
from t_test_grade2
union
select user_name, '数学' COURSE, math_score as SCORE
from t_test_grade2
order by user_name, COURSE;
select * from T_TEST_GRADE3 t;
create table T_TEST_GRADE3
(
USER_NAME VARCHAR2(20),
COURSE VARCHAR2(20),
SCORE VARCHAR2(20)
);
insert all
into t_test_grade3(USER_NAME,COURSE,SCORE) values(user_name, '英语', english_score)
into t_test_grade3(USER_NAME,COURSE,SCORE) values(user_name, '篮球', basketball_score)
into t_test_grade3(USER_NAME,COURSE,SCORE) values(user_name, '数学', math_score)
select user_name, english_score, basketball_score, math_score from t_test_grade2;