Oracle 行轉列和列轉行

一、行轉列

1.1、初始測試數據

表結構:TEST_TB_GRADE

Sql代碼:

?
1
2
3
4
5
6
7
createtableTEST_TB_GRADE
(
  ID        NUMBER(10) notnull,
  USER_NAME VARCHAR2(20 CHAR),
  COURSE    VARCHAR2(20 CHAR),
  SCORE    FLOAT
)


初始數據如下圖:  

insert into test_tb_grade values(1, 'aa', 'Math', 80.0);
insert into test_tb_grade values(2, 'aa', 'English', 90.0);
insert into test_tb_grade values(3, 'bb', 'Math', 70.0);
insert into test_tb_grade values(4, 'bb', 'English', 60.0);
commit;

1.2、 如果需要實現如下的查詢效果圖:

  

這就是最常見的行轉列,主要原理是利用decode函數、聚集函數(sum),結合group by分組實現的,具體的sql如下:

Sql代碼:

SELECT user_name,
  SUM(DECODE(course, 'Math', score, NULL))    AS MATH,
  SUM(DECODE(course, 'English', score, NULL)) AS ENGLISH
FROM test_tb_grade
GROUP BY user_name
ORDER BY user_name;

?

1.3、延伸

如果要實現對各門功課的不同分數段進行統計,效果圖如下:

      

具體的實現sql如下:
Sql代碼:

SELECT t2.SCORE_GP,
  SUM(DECODE(t2.course,'Math', COUNTNUM,NULL))    AS MATH,
  SUM(DECODE(t2.course,'English', 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 
Sql代碼:  
?
1
2
3
4
5
6
7
8
createtableTEST_TB_GRADE2
(
  ID         NUMBER(10) notnull,
  USER_NAME  VARCHAR2(20 CHAR),
  CN_SCORE  FLOAT,
  MATH_SCOREFLOAT,
  EN_SCORE  FLOAT
)

初始數據如下圖


  insert into TEST_TB_GRADE2 values(1, 'aa', 50, 60, 70);
  insert into TEST_TB_GRADE2 values(1, 'bb', 60, 70, 80);
  insert into TEST_TB_GRADE2 values(1, 'cc', 80, 90, 100);
  insert into TEST_TB_GRADE2 values(1, 'dd', 100, 90, 80);
  commit;



1.2、 如果需要實現如下的查詢效果圖:

 

這就是最常見的列轉行,主要原理是利用SQL裏面的union,具體的sql語句如下:
Sql代碼: 

SELECT user_name, 
  'CN_SCORE' AS COURSE, 
  CN_SCORE AS SCORE 
FROM test_tb_grade2
UNION
SELECT user_name,
  'MATH_SCORE' AS COURSE,
  MATH_SCORE   AS SCORE
FROM test_tb_grade2
UNION
SELECT user_name,
  'EN_SCORE' AS COURSE,
  EN_SCORE   AS SCORE
FROM test_tb_grade2
ORDER BY user_name,COURSE;


?

也可以利用【insert all into ... select】來實現,首先需要先建一個表TEST_TB_GRADE3

Sql代碼:  
?
1
2
3
4
5
6
createtableTEST_TB_GRADE3  
      USER_NAME VARCHAR2(20 CHAR),  
      COURSE    VARCHAR2(20 CHAR),  
      SCORE    FLOAT  
)
   
 再執行下面的sql: 

  Sql代碼:  

INSERT ALL
INTO test_tb_grade3
  (
    USER_NAME,
    COURSE,
    SCORE
  )
  VALUES
  (
    user_name,
    'Chinese',
    CN_SCORE
  )
INTO test_tb_grade3
  (
    USER_NAME,
    COURSE,
    SCORE
  )
  VALUES
  (
    user_name,
    'Math',
    MATH_SCORE
  )
INTO test_tb_grade3
  (
    USER_NAME,
    COURSE,
    SCORE
  )
  VALUES
  (
    user_name,
    'English',
    EN_SCORE
  )
SELECT user_name, CN_SCORE, MATH_SCORE, EN_SCORE FROM test_tb_grade2;
COMMIT;


 別忘記commit操作,然後再查詢TEST_TB_GRADE3,發現表中的數據就是列轉成行了。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章