oracle列轉行和行轉列

行轉列

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的字段值,表示分數。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章