Oracle交叉表的实现的正确姿势

Oracle行转列Sql语句示例

-- 创建表
CREATE TABLE T_TEST_PIVOT(QUESTIONS_NAME VARCHAR(50),QUESTIONS_ID VARCHAR(50),SCORE NUMBER);  

INSERT INTO T_TEST_PIVOT VALUES('13-16', '5F12FA99716F4E0B9C15F0715C1FC956', 10);
INSERT INTO T_TEST_PIVOT VALUES('17', 'A432D69066A34FA29F21607E82AB2770', 8);
INSERT INTO T_TEST_PIVOT VALUES('18', '8A7D1130EE074B2B92480B48D4EF28B3', 12);
INSERT INTO T_TEST_PIVOT VALUES('19', 'E287E2BDB959475FA888863BBC143E7A', 10);
INSERT INTO T_TEST_PIVOT VALUES('20', 'C55136B256074761AF582ADD20324CF1', 9);
INSERT INTO T_TEST_PIVOT VALUES('21', '26E96EB33FDB4D3687F48080ABF89243', 2.33);
INSERT INTO T_TEST_PIVOT VALUES('22', '0908C33717864EB9A5AC6B183A218CF2', 7);

COMMIT;

SELECT * FROM T_TEST_PIVOT

-- 分组查询
SELECT QUESTIONS_NAME
       ,SUM(SCORE) SCORE 
 FROM T_TEST_PIVOT 
 GROUP BY QUESTIONS_NAME

-- 行转列查询
SELECT * FROM 
      (SELECT QUESTIONS_NAME, SCORE FROM T_TEST_PIVOT) 
    PIVOT (SUM(SCORE) FOR QUESTIONS_NAME 
    IN ('13-16' "13-16", '17', '18', '19', '20', '21', '22'));

报表示例:

Oracle交叉表的实现的正确姿势_第1张图片
报表示例01.png

实现步骤

步骤1,得到某个考试科目ID的所有题(包含主客观题)所有给分序列

-- 得到某个考试科目ID的所有题(包含主客观题)所有给分序列
-- 客观题,列转行
SELECT * FROM (
 SELECT CAST(SCORE AS DECIMAL(10,2)) SCORE_DETAIL
  FROM (
   SELECT T.QUESTIONS_ID,
       T.EXAM_COURSE_ID,
       T1.ROW_INDEX,
       REGEXP_SUBSTR(T.FULL_SCORE ,'[^,]+',1,T1.ROW_INDEX) SCORE
  FROM T_TPL_OBJECTIVE_QUESTIONS T,
  (SELECT LEVEL ROW_INDEX FROM DUAL CONNECT BY LEVEL<=200) T1
  WHERE T1.ROW_INDEX <= LENGTH(T.FULL_SCORE) - LENGTH(REPLACE(T.FULL_SCORE,',')) + 1  
  AND T.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0' ) M2 GROUP BY SCORE
UNION 
  SELECT M1.SCORE
     FROM (

  SELECT T2.QUESTIONS_ID
        ,T2.SCORE
        ,T3.SERIAL_NO
         ,COUNT(*) CNT1
  FROM T_RVW_FINAL T2 
  INNER JOIN T_TPL_SUBJECTIVE_QUESTIONS T3 ON T2.EXAM_COURSE_ID = T3.EXAM_COURSE_ID AND T2.QUESTIONS_ID = T3.QUESTIONS_ID
  WHERE T2.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0'
  GROUP BY T2.QUESTIONS_ID,T2.SCORE,T3.SERIAL_NO  
  ) M1 GROUP BY M1.SCORE  ) L

步骤2,客观题

SELECT * FROM (
SELECT 
        T1.EXAM_COURSE_ID
        ,T6.ORG_ID
        ,T6.ORG_NAME
        ,T5.CLASS_ID
        ,T5.CLASS_NAME
        ,(CASE WHEN EXTRACT(MONTH FROM SYSDATE) >= 9 
               THEN EXTRACT(YEAR FROM SYSDATE) - REG_YEAR + 1 
               ELSE EXTRACT(YEAR FROM SYSDATE) - REG_YEAR END) || '年级' GRADE
        ,T1.QUESTIONS_ID
        ,T1.QUESTIONS_NAME
        ,T1.SCORE FULL_SCORE
        ,T1.SERIAL_NO
        ,T2.SCORE
        ,(SELECT COUNT(1) FROM V_RPT_COURSE_STUDENT V 
            WHERE V.EXAM_COURSE_ID = T1.EXAM_COURSE_ID
            AND V.ORG_ID = T6.ORG_ID
           AND V.CLASS_ID = T5.CLASS_ID) ACTUAL_CNT
        ,COUNT(1) SCORE_CNT  -- 某道题某个分值的得分人数
        ,ROUND((COUNT(1) / (SELECT COUNT(1) FROM V_RPT_COURSE_STUDENT V 
            WHERE V.EXAM_COURSE_ID = T1.EXAM_COURSE_ID
            AND V.ORG_ID = T6.ORG_ID
           AND V.CLASS_ID = T5.CLASS_ID))* 100 ,2) AS SCORE_PRECENT   -- 得分率
           
        ,MAX(M1.AVG_SCORE) AVG_SCORE
        ,MAX(M1.STDDEV_SCORE) STDDEV_SCORE
        ,1 QUESTION_TYPE
        
     FROM T_TPL_OBJECTIVE_QUESTIONS T1 
         INNER JOIN V_RPT_OBJECTIVE_QUESTIONS T2 ON T1.EXAM_COURSE_ID = T2.EXAM_COURSE_ID AND T1.QUESTIONS_ID = T2.QUESTIONS_ID
         INNER JOIN T_EMS_EXAM_STUDENT T3 ON T2.TEST_NO = T3.TEST_NO AND T2.EXAM_COURSE_ID = T3.EXAM_COURSE_ID
         INNER JOIN T_BAS_STUDENT T4 ON T3.STUDENT_ID = T4.STUDENT_ID
         INNER JOIN T_BAS_CLASS T5 ON T4.CLASS_ID = T5.CLASS_ID
         INNER JOIN T_BAS_ORGANIZATION T6 ON T5.ORG_ID = T6.ORG_ID
         
         INNER JOIN (SELECT 
          T1.EXAM_COURSE_ID
          ,T1.QUESTIONS_ID
          ,ROUND(AVG(T2.SCORE),2) AVG_SCORE
          ,ROUND(STDDEV(T2.SCORE),2) STDDEV_SCORE
              
    FROM T_TPL_OBJECTIVE_QUESTIONS T1
         INNER JOIN V_RPT_OBJECTIVE_QUESTIONS T2 ON T1.EXAM_COURSE_ID = T2.EXAM_COURSE_ID AND T1.QUESTIONS_ID = T2.QUESTIONS_ID
         INNER JOIN T_EMS_EXAM_STUDENT T3 ON T2.TEST_NO = T3.TEST_NO AND T2.EXAM_COURSE_ID = T3.EXAM_COURSE_ID
         INNER JOIN T_BAS_STUDENT T4 ON T3.STUDENT_ID = T4.STUDENT_ID
         INNER JOIN T_BAS_CLASS T5 ON T4.CLASS_ID = T5.CLASS_ID
         INNER JOIN T_BAS_ORGANIZATION T6 ON T5.ORG_ID = T6.ORG_ID
       WHERE T1.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0'
         AND T6.ORG_ID = '16AD9626CA8044CE81CDA692B896B600'
         AND T5.CLASS_ID = '73B41F587651422089C8B7518168F4E8'
             
         GROUP BY T1.EXAM_COURSE_ID
                ,T1.QUESTIONS_ID ) M1 ON T1.EXAM_COURSE_ID = M1.EXAM_COURSE_ID AND T1.QUESTIONS_ID = M1.QUESTIONS_ID
                
         
         
       WHERE T1.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0'
         AND T6.ORG_ID = '16AD9626CA8044CE81CDA692B896B600'
         AND T5.CLASS_ID = '73B41F587651422089C8B7518168F4E8'
         
 GROUP BY T1.EXAM_COURSE_ID
            ,T1.QUESTIONS_ID
            ,T1.QUESTIONS_NAME
            ,T1.SCORE
            ,T1.SERIAL_NO
            ,T2.SCORE
            ,T6.ORG_ID
            ,T6.ORG_NAME
            ,T5.CLASS_ID
            ,T5.CLASS_NAME
            ,T5.REG_YEAR 
       )     
 PIVOT (
            -- 注意这里的写法;
             SUM(SCORE_CNT) 人数
            ,SUM(SCORE_PRECENT) 得分率 
            FOR SCORE
            IN ('0' "0"
                 ,'0.5' "0.5"
                 ,'1' "1"
                 ,'1.5' "1.5"
                 ,'2' "2"
                 ,'2.5' "2.5"
                 ,'3' "3"
                 ,'3.5' "3.5"
                 ,'4' "4"
                 ,'4.5' "4.5"
                 ,'5' "5"
                 ,'6' "6"
                 ,'6.5' "6.5"
                 ,'7' "7")
                )         

步骤3,主观题

SELECT * FROM (
      SELECT 
         T1.EXAM_COURSE_ID
        ,T6.ORG_ID
        ,T6.ORG_NAME
        ,T5.CLASS_ID
        ,T5.CLASS_NAME
        ,(CASE WHEN EXTRACT(MONTH FROM SYSDATE) >= 9 
               THEN EXTRACT(YEAR FROM SYSDATE) - REG_YEAR + 1 
               ELSE EXTRACT(YEAR FROM SYSDATE) - REG_YEAR END) || '年级' GRADE
        ,T1.QUESTIONS_ID
        ,T1.QUESTIONS_NAME
        ,T1.FULL_SCORE
        ,T1.SERIAL_NO
        ,T2.SCORE
        ,(SELECT COUNT(1) FROM V_RPT_COURSE_STUDENT V 
            WHERE V.EXAM_COURSE_ID = T1.EXAM_COURSE_ID
            AND V.ORG_ID = T6.ORG_ID
           AND V.CLASS_ID = T5.CLASS_ID) ACTUAL_CNT
        ,COUNT(1) SCORE_CNT  -- 某道题某个分值的得分人数
        ,ROUND((COUNT(1) / (SELECT COUNT(1) FROM V_RPT_COURSE_STUDENT V 
            WHERE V.EXAM_COURSE_ID = T1.EXAM_COURSE_ID
            AND V.ORG_ID = T6.ORG_ID
           AND V.CLASS_ID = T5.CLASS_ID))* 100 ,2) AS SCORE_PRECENT   -- 得分率
        ,MAX(M1.AVG_SCORE) AVG_SCORE
        ,MAX(M1.STDDEV_SCORE) STDDEV_SCORE
        ,2 QUESTION_TYPE
        
   FROM T_TPL_SUBJECTIVE_QUESTIONS T1 
     INNER JOIN T_RVW_FINAL T2 ON T1.EXAM_COURSE_ID = T2.EXAM_COURSE_ID AND T1.QUESTIONS_ID = T2.QUESTIONS_ID
     INNER JOIN T_EMS_EXAM_STUDENT T3 ON T2.TEST_NO = T3.TEST_NO AND T2.EXAM_COURSE_ID = T3.EXAM_COURSE_ID
     INNER JOIN T_BAS_STUDENT T4 ON T3.STUDENT_ID = T4.STUDENT_ID
     INNER JOIN T_BAS_CLASS T5 ON T4.CLASS_ID = T5.CLASS_ID
     INNER JOIN T_BAS_ORGANIZATION T6 ON T5.ORG_ID = T6.ORG_ID
     
     INNER JOIN (SELECT 
          T1.EXAM_COURSE_ID
          ,T1.QUESTIONS_ID
          ,ROUND(AVG(T2.SCORE),2) AVG_SCORE
          ,ROUND(STDDEV(T2.SCORE),2) STDDEV_SCORE
              
    FROM T_TPL_SUBJECTIVE_QUESTIONS T1
         INNER JOIN T_RVW_FINAL T2 ON T1.EXAM_COURSE_ID = T2.EXAM_COURSE_ID AND T1.QUESTIONS_ID = T2.QUESTIONS_ID
         INNER JOIN T_EMS_EXAM_STUDENT T3 ON T2.TEST_NO = T3.TEST_NO AND T2.EXAM_COURSE_ID = T3.EXAM_COURSE_ID
         INNER JOIN T_BAS_STUDENT T4 ON T3.STUDENT_ID = T4.STUDENT_ID
         INNER JOIN T_BAS_CLASS T5 ON T4.CLASS_ID = T5.CLASS_ID
         INNER JOIN T_BAS_ORGANIZATION T6 ON T5.ORG_ID = T6.ORG_ID
       WHERE T1.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0'
         AND T6.ORG_ID = '16AD9626CA8044CE81CDA692B896B600'
         AND T5.CLASS_ID = '73B41F587651422089C8B7518168F4E8'
             
         GROUP BY T1.EXAM_COURSE_ID
                ,T1.QUESTIONS_ID ) M1 ON T1.EXAM_COURSE_ID = M1.EXAM_COURSE_ID AND T1.QUESTIONS_ID = M1.QUESTIONS_ID

     
   WHERE T1.EXAM_COURSE_ID = 'D87C1D2C4102472499C80B676DECF4C0'
     AND T6.ORG_ID = '16AD9626CA8044CE81CDA692B896B600'
     AND T5.CLASS_ID = '73B41F587651422089C8B7518168F4E8'
     
   GROUP BY T1.EXAM_COURSE_ID
            ,T1.QUESTIONS_ID
            ,T1.QUESTIONS_NAME
            ,T1.FULL_SCORE
            ,T1.SERIAL_NO
            ,T2.SCORE
            ,T6.ORG_ID
            ,T6.ORG_NAME
            ,T5.CLASS_ID
            ,T5.CLASS_NAME
            ,T5.REG_YEAR
          ) 
          PIVOT (
            -- 注意这里的写法;
             SUM(SCORE_CNT) 人数
            ,SUM(SCORE_PRECENT) 得分率 FOR SCORE
            IN ('0' "0"
                 ,'0.5' "0.5"
                 ,'1' "1"
                 ,'1.5' "1.5"
                 ,'2' "2"
                 ,'2.5' "2.5"
                 ,'3' "3"
                 ,'3.5' "3.5"
                 ,'4' "4"
                 ,'4.5' "4.5"
                 ,'5' "5"
                 ,'6' "6"
                 ,'6.5' "6.5"
                 ,'7' "7")
                )

你可能感兴趣的:(Oracle交叉表的实现的正确姿势)