行转列
table
DROP TABLE "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET";
CREATE TABLE "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" (
"ID" VARCHAR2(64 BYTE) NOT NULL ,
"DATE_TIME" DATE NULL ,
"COMPANY_ID" VARCHAR2(20 BYTE) NULL ,
"CREATE_TIME" DATE NULL ,
"UPDATE_TIME" DATE NULL ,
"DEL_FLAG" VARCHAR2(1 BYTE) DEFAULT '0' NULL ,
"LINK" NUMBER NULL ,
"PROPORTION" NUMBER(10,4) NULL
);
COMMENT ON TABLE "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" IS '各环节责任承担比例预算';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."DATE_TIME" IS '预算时间';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."COMPANY_ID" IS '责任单位id(省份或集团),对应b_owner的owner_id';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."CREATE_TIME" IS '创建时间';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."UPDATE_TIME" IS '修改时间';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."DEL_FLAG" IS '逻辑删除,0正常,1删除';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."LINK" IS '责任环节(0公司、1平台、2直营、3特许、4干线)';
COMMENT ON COLUMN "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET"."PROPORTION" IS '所占比例';
-- ----------------------------
-- Records of BR_CLAIM_PROPORTION_BUDGET
-- ----------------------------
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('4', TO_DATE('2020-03-01 16:37:49', 'YYYY-MM-DD HH24:MI:SS'), '1551001', null, TO_DATE('2020-03-11 18:54:36', 'YYYY-MM-DD HH24:MI:SS'), '0', '1', '0.20');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('6', TO_DATE('2020-03-01 16:37:49', 'YYYY-MM-DD HH24:MI:SS'), '1551001', null, TO_DATE('2020-03-11 18:54:36', 'YYYY-MM-DD HH24:MI:SS'), '0', '4', '0.20');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('5', TO_DATE('2020-03-01 16:37:49', 'YYYY-MM-DD HH24:MI:SS'), '1551001', null, TO_DATE('2020-03-11 18:54:36', 'YYYY-MM-DD HH24:MI:SS'), '0', '2', '0.30');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('7', TO_DATE('2020-03-01 16:37:49', 'YYYY-MM-DD HH24:MI:SS'), '1551001', null, TO_DATE('2020-03-11 18:54:36', 'YYYY-MM-DD HH24:MI:SS'), '0', '0', '0.20');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('1', TO_DATE('2020-03-01 16:37:49', 'YYYY-MM-DD HH24:MI:SS'), '1551001', null, TO_DATE('2020-03-11 18:54:36', 'YYYY-MM-DD HH24:MI:SS'), '0', '3', '0.10');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('2', TO_DATE('2019-01-05 18:09:09', 'YYYY-MM-DD HH24:MI:SS'), '1027001', null, TO_DATE('2020-03-11 18:48:10', 'YYYY-MM-DD HH24:MI:SS'), '0', '3', '0.7896');
INSERT INTO "DEMO_USER"."BR_CLAIM_PROPORTION_BUDGET" VALUES ('3', TO_DATE('2019-01-11 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), '1311001', TO_DATE('2020-03-11 18:52:48', 'YYYY-MM-DD HH24:MI:SS'), TO_DATE('2020-03-11 18:23:32', 'YYYY-MM-DD HH24:MI:SS'), '0', '4', '0.7896');
原始数据显示样式
表中显示的是公司各环节责任承担比例预算,每个公司都有5个环节(link的值表示不同的环节)
想要的样式
现在想行转列,显示成
具体操作
使用decode或者case... when实现
SELECT
p.COMPANY_ID as companyId,
b.OWNER_NAME as companyName,
sum(case when p.link=0 then p.PROPORTION else 0 end) as company,
sum(DECODE(p.link,1,p.PROPORTION,0)) as platform,
sum(DECODE(p.link,2,p.PROPORTION,0)) as direct,
sum(DECODE(p.link,3,p.PROPORTION,0)) as charter,
sum(DECODE(p.link,4,p.PROPORTION,0)) as line
FROM BR_CLAIM_PROPORTION_BUDGET p,b_owner b
WHERE p.COMPANY_ID = b.OWNER_ID and p.del_flag = '0'
GROUP BY p.COMPANY_ID,b.OWNER_NAME,p.DATE_TIME
ORDER BY p.DATE_TIME DESC
注意:
1、因为使用了sum,所以decode的默认值最好不要写成null——sum(DECODE(p.link,1,p.PROPORTION,null)),最好写成0——sum(DECODE(p.link,1,p.PROPORTION,0))
2、如果字符串为汉字的时候需要用双引号,而不是单引号,如
双引号的话
别名为字母的话则不需要用引号
或者使用pivot实现行转列
SELECT companyId,companyName,company,platform,direct,charter,line
FROM(
SELECT p.company_id companyId ,b.owner_name companyName,p.link link,p.proportion proportion
from BR_CLAIM_PROPORTION_BUDGET p,B_OWNER b
WHERE p.company_id = b.owner_id
) T
pivot(sum(proportion) FOR link IN(0 as company,1 as platform,2 as direct,3 as charter,4 as line))
其他实例
转自:https://blog.csdn.net/jumtre/article/details/46473729
[一]、行转列
1.1、初始测试数据
表结构:TEST_TB_GRADE
create table TEST_TB_GRADE
(
ID NUMBER(10) not null,
USER_NAME VARCHAR2(20 CHAR),
COURSE VARCHAR2(20 CHAR),
SCORE FLOAT
)
初始数据如下图:
1.2、 如果需要实现如下的查询效果图:
这就是最常见的行转列,主要原理是利用decode函数、聚集函数(sum),结合group by分组实现的,具体的sql如下:
select t.user_name,
sum(decode(t.course, '语文', score,null)) as CHINESE,
sum(decode(t.course, '数学', score,null)) as MATH,
sum(decode(t.course, '英语', score,null)) as ENGLISH
from test_tb_grade t
group by t.user_name
order by t.user_name
1.3、延伸
如果要实现对各门功课的不同分数段进行统计,效果图如下:
具体的实现sql如下:
select t2.SCORE_GP,
sum(decode(t2.course, '语文', COUNTNUM,null)) as CHINESE,
sum(decode(t2.course, '数学', COUNTNUM,null)) as MATH,
sum(decode(t2.course, '英语', COUNTNUM,null)) as ENGLISH
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 SCORE_GP,
count(t.score) as COUNTNUM
FROM test_tb_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.SCORE_GP
order by t2.SCORE_GP
[二]、列转行
1.1、初始测试数据
表结构:TEST_TB_GRADE2
create table TEST_TB_GRADE2
(
ID NUMBER(10) not null,
USER_NAME VARCHAR2(20 CHAR),
CN_SCORE FLOAT,
MATH_SCORE FLOAT,
EN_SCORE FLOAT
)
初始数据如下图:
1.2、 如果需要实现如下的查询效果图:
这就是最常见的列转行,主要原理是利用SQL里面的union,具体的sql语句如下:
select user_name, '语文' COURSE , CN_SCORE as SCORE from test_tb_grade2
union select user_name, '数学' COURSE, MATH_SCORE as SCORE from test_tb_grade2
union select user_name, '英语' COURSE, EN_SCORE as SCORE from test_tb_grade2
order by user_name,COURSE
也可以利用【 insert all into ... select 】来实现,首先需要先建一个表TEST_TB_GRADE3:
Sql代码
create table TEST_TB_GRADE3
(
USER_NAME VARCHAR2(20 CHAR),
COURSE VARCHAR2(20 CHAR),
SCORE FLOAT
)
再执行下面的sql:
insert all
into test_tb_grade3(USER_NAME,COURSE,SCORE) values(user_name, '语文', CN_SCORE)
into test_tb_grade3(USER_NAME,COURSE,SCORE) values(user_name, '数学', MATH_SCORE)
into test_tb_grade3(USER_NAME,COURSE,SCORE) values(user_name, '英语', EN_SCORE)
select user_name, CN_SCORE, MATH_SCORE, EN_SCORE from test_tb_grade2;
commit;
别忘记commit操作,然后再查询TEST_TB_GRADE3,发现表中的数据就是列转成行了。
使用PIVOT和UNPIVOT
转自:https://blog.csdn.net/leq3915/article/details/80460316
行转列:PIVOT
列转行:UNPIVOT
这两个是在oracle11g上面新增的函数。下面举例说明用法。
PIVOT:
学生成绩表,原数据:
select class_name, student_name, course_type, result, created_date
from class_tmp_2;
每个同学的两门成绩,是两条数据,因为业务需要,展示给用户看的时候,用户想要每个同学只要一条数据,并且把所有成绩都展示出来,比如
这个时候就需要用到行专列函数PIVOT.
SELECT class_name, student_name, 语文, 数学, created_date
FROM (SELECT CLASS_NAME, STUDENT_NAME, COURSE_TYPE, RESULT, CREATED_DATE
FROM CLASS_TMP_2) T
PIVOT(SUM(RESULT)
FOR COURSE_TYPE IN('语文' AS 语文, '数学' AS 数学));
浅灰色的sql和上面的原数据sql一样,主要看一下后面的PIVOT部分。
sum(result):成绩之和(PIVOT内需有聚集函数)
for course_type in ('语文' as语文, '数学' as数学):将course_type列的字段值转换成列名,其中,字段值是'语文',转换成语文列,字段值是'数学',转换成数学列,这两列的字段值,即前面的sum(result)。
不用函数也可以得到,如下sql:
select t1.class_name,
t1.student_name,
t1.result 语文,
t2.result 数学,
t1.created_date
from (select a.class_name,
a.student_name,
a.course_type,
a.result,
a.created_date
from class_tmp_2 a
where a.course_type = '语文') t1,
(select a.class_name,
a.student_name,
a.course_type,
a.result,
a.created_date
from class_tmp_2 a
where a.course_type = '数学') t2
where t1.class_name = t2.class_name
and t1.student_name = t2.student_name;
UNPIVOT:列转行
反过来,原数据如下:
而我想要得到的结果如下:
SQL:
select class_name, student_name, course_type, result, created_date
from class_tmp
unpivot(result for course_type in(chinese_result,math_result));
原数据的chinese_result列和math_result列的列名(浅灰色),将转换为新建列course_type的字段值,表示课种。
原数据的chinese_result列和math_result列的字段值,将转换为新建列result的字段值,表示分数。