Oracle SQL PIVOT:缺少列和聚合行?

时间:2015-05-28 16:04:43

标签: sql oracle pivot

我正在尝试找一张能够显示学生每月出勤详情的表格。
我所拥有的是一个根据学生课程负荷总结缺勤数量的支点。
比方说,我知道这个学生一直有4节课,无论是学年还是学期,this would work perfectly

SELECT * FROM

(SELECT SCHOOL_YEAR, TO_CHAR(CALENDAR_DATE, 'mon') MNTH, ATTENDANCE_CODE 

FROM PERIOD_ATTENDANCE

WHERE PERSON_ID = '1234'
AND SCHOOL_CODE IN ('ESS', 'ASS', 'BSS')
) 


PIVOT (SUM(CASE WHEN ATTENDANCE_CODE = 'L' THEN 1 END) as L, 
       SUM(CASE WHEN ATTENDANCE_CODE = 'A' 
                AND MNTH IN ('sep', 'oct', 'nov', 'dec', 'jan')
                THEN 1/4
                WHEN ATTENDANCE_CODE = 'A'
                AND MNTH IN ('feb', 'mar', 'apr', 'may', 'jun')
                THEN 1/4 END) as A
       FOR MNTH
       IN (     
                'sep',-- AS SEPTEMBRE,
                'oct',-- AS OCTOBRE,
                'nov',-- AS NOVEMBRE, 
                'dec',-- AS DECEMBRE,
                'jan', -- AS JANVIER, 
                'feb',-- AS FÉVRIER, 
                'mar',-- AS MARS,
                'apr',-- AS AVRIL,
                'may',-- AS MAI, 
                'jun'-- AS JUIN

            ) -- END <IN>
) -- END PIVOT

但由于有些学生每学期学习的课程少于或多于平均4门课程,我需要找到一种方法,使“4”(“THEN 1/4 END”)代表学生的实际课程数量正在服用。
我想出了一个返回这个数字的函数,但是一旦我将它插入到数据透视表中,查询只返回一行,它显示了每年学生缺勤的总和。

PIVOT (SUM(CASE WHEN ATTENDANCE_CODE = 'L' THEN 1 END) as L, 
           SUM(CASE WHEN ATTENDANCE_CODE = 'A' 
                    AND MNTH IN ('sep', 'oct', 'nov', 'dec', 'jan')
                    THEN 1/PKG_PROFILE_ÉLÈVE.GET_COURSE_COUNT(SCHOOL_YEAR, '123456789', 1)
                    WHEN ATTENDANCE_CODE = 'A'
                    AND MNTH IN ('feb', 'mar', 'apr', 'may', 'jun')
                    THEN 1/PKG_PROFILE_ÉLÈVE.GET_COURSE_COUNT(SCHOOL_YEAR, '123456789', 2) END) as A

它返回以下内容,您会注意到school_year列也已消失。

'sep'_L    'sep'_A    'oct'_L    'oct'_A    'nov'_L    'nov'_A    'dec'_L    'dec'_A    'jan'_L    'jan'_A    'feb'_L    'feb'_A    'mar'_L    'mar'_A    'apr'_L    'apr'_A    'may'_L    'may'_A    'jun'_L    'jun'_A
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
    2        0.25          2                              0.75        2         0.25       1          1.75        2          1           7        0.75         1        0.25         1         0.25       1        0.25

无论函数中的实际内容如何,​​都会发生这种情况。功能可以 简单如下,它仍将返回单个聚合行。

FUNCTION GET_COURSE_COUNT(A_SCHOOL_YEAR VARCHAR2, A_PERSON_ID VARCHAR2, A_SEMESTER VARCHAR2) RETURN NUMBER IS
NUM_COURSE NUMBER := NULL;

BEGIN
NUM_COURSE = 4;

RETURN NUM_COURSE;
END GET_COURSE_COUNT;

有人知道这是否是由于PIVOT功能本身引起的?函数是否以某种方式强制聚合和行的总和? 我现在已经看了两天了,我似乎无法找到这样的事情。它一定是显而易见的我错过了......

实际功能如下:

FUNCTION GET_COURSE_COUNT(A_SCHOOL_YEAR VARCHAR2, A_PERSON_ID VARCHAR2, A_SEMESTER VARCHAR2) RETURN NUMBER IS
NUM_COURSE NUMBER := NULL;

BEGIN 

SELECT
       COUNT( CASE --total des cours prit durant le semestre spécifié
              WHEN SEMESTER = A_SEMESTER 
              THEN SEMESTER END) AS SEMESTRE INTO NUM_COURSE

FROM (SELECT DISTINCT SCT.SCHOOL_YEAR, 
                SCT.COURSE_CODE || '-' || SCT.COURSE_SECTION AS COURSE, 
                SC.TAKE_ATTENDANCE_FLAG, CM.SEMESTER

FROM SCHOOL_CLASSES SC, STUDENT_PROGRAM_CLASS_TRACKS SCT, CLASS_MEETINGS CM 

WHERE SCT.PERSON_ID = A_PERSON_ID
    AND SCT.SCHOOL_CODE IN ('ESS', 'ASS', 'BSS')
    AND SC.SCHOOL_CODE = SCT.SCHOOL_CODE
    AND SCT.SCHOOL_YEAR = A_SCHOOL_YEAR
    AND SC.SCHOOL_YEAR = SCT.SCHOOL_YEAR
    AND SC.CLASS_CODE = SCT.CLASS_CODE
    AND SCT.SCHOOL_CODE = CM.SCHOOL_CODE
    AND SCT.CLASS_CODE = CM.CLASS_CODE
    AND CM.SCHOOL_YEAR = SCT.SCHOOL_YEAR
    AND SCT.SCHOOL_YEAR_TRACK = CM.SCHOOL_YEAR_TRACK
    AND SCT.DEMIT_INDICATOR NOT IN ('9')


ORDER BY SCT.SCHOOL_YEAR, CM.SEMESTER, COURSE);


RETURN NUM_COURSE;
END GET_COURSE_COUNT;

1 个答案:

答案 0 :(得分:2)

请尝试此查询:

SELECT * FROM
  (SELECT SCHOOL_YEAR, TO_CHAR(CALENDAR_DATE, 'MM') MNTH, ATTENDANCE_CODE, 
      GET_COURSE_COUNT(SCHOOL_YEAR, '123456789', 
        case when TO_CHAR(CALENDAR_DATE, 'MM') IN ('09','10','11','12','01') 
             then 1 else 2 end) gcc 
    FROM PERIOD_ATTENDANCE
    WHERE PERSON_ID = '1234' AND SCHOOL_CODE IN ('ESS', 'ASS', 'BSS')) 
PIVOT (
  SUM(CASE WHEN ATTENDANCE_CODE = 'L' THEN 1 END) as L, 
  SUM(CASE WHEN ATTENDANCE_CODE = 'A' THEN 1/gcc END) as A
  FOR MNTH IN ('09','10','11','12','01','02','03','04','05','06'))

我认为pivot子句中使用的每一列都是聚合的,在这种情况下,school_year用作函数的参数,因此它也被聚合 - 所以解决方案应该是将函数移动到基础子查询。此外,当我从函数定义中删除此参数时,行未加入。

请使用您的数据和计算验证最终结果。