Oracle SQL查询帮助 - 学生出勤

时间:2017-12-14 00:47:12

标签: sql

我在下面的查询中提取了参加体育或学校活动的学生的每日出勤率(1到10期)。我只想看到其中一个时期至少有一个缺席的学生,所以如果所有时期的出勤代码都是NULL,则不应出现。我不知道如何将其添加到查询中。有人可以帮忙吗?

 SELECT DISTINCT 
      s.student_number AS "Student Number", 
      s.lastfirst AS "Student Name", 
      DECODE(s.grade_level,-1,'PK',0,'KG',s.grade_level) AS "Grade", 
      s.home_phone AS "Phone", 
      DECODE(s.schoolid,280050,'Kodiak High School',s.schoolid) AS "School",
      (SELECT DISTINCT co.course_name FROM ps.courses WHERE co.course_number=se.course_number AND se.course_number LIKE 'CLB%' OR se.course_number LIKE 'ACT%') AS "Course Name",
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='1') AS "Per. 1", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='2') AS "Per. 2", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='3') AS "Per. 3", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='4') AS "Per. 4", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='5') AS "Per. 5", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='6') AS "Per. 6", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='7') AS "Per. 7", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='8') AS "Adv", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='9') AS "Act", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='10') AS "Clb" 

      FROM attendance att 
      JOIN students s ON s.id=att.studentid 
      INNER JOIN cc ON s.ID=cc.studentid 
      INNER JOIN sections se ON cc.sectionid = se.id
      JOIN courses co ON co.course_number=se.COURSE_NUMBER

      WHERE att.att_date=to_date(SYSDATE) 
      AND att.schoolid in '280050'
      AND s.enroll_status=0 
      AND cc.termid = 2700 
      AND se.course_number LIKE 'ACT%'OR se.course_number LIKE 'CLB%'

      ORDER BY s.lastfirst

以下是数据示例。所有句点都为NULL时,我不希望看到行。只有他们有缺席代码。Data Sample

4 个答案:

答案 0 :(得分:0)

虽然我对你正在处理的数据知之甚少,但我想建议这是一个起点:

SELECT
        studentid
      , max(case when period_number='1'  then attcodes end) per1
      , max(case when period_number='2'  then attcodes end) per2
      , max(case when period_number='3'  then attcodes end) per3
      , max(case when period_number='4'  then attcodes end) per4
      , max(case when period_number='5'  then attcodes end) per5
      , max(case when period_number='6'  then attcodes end) per6
      , max(case when period_number='7'  then attcodes end) per7
      , max(case when period_number='8'  then attcodes end) per8
      , max(case when period_number='9'  then attcodes end) per9
      , max(case when period_number='10' then attcodes end) per10
FROM (
      SELECT
              attm.studentid
            , attm.period_number
            , listagg(attm.att_code,'|') within group (order by attm.att_code) attcodes
      FROM pssis_attendance_meeting attm 
      WHERE attm.att_date=to_date(SYSDATE) 
      AND attm.att_code IS NOT NULL 
      GROUP BY
              attm.studentid
            , attm.period_number
      ) d
GROUP BY
        studentid
;

这将为每位学生生成一行,其中包含10列出勤代码。我不知道为什么你会在一段时间内有多个出勤代码,但我继续使用listagg()以防万一。

在此查询中,逻辑会删除当天未注册出席代码的所有学生。

我希望这可以帮助您找到整体解决方案。

修改

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE PSSIS_ATTENDANCE_MEETING
    (NAME varchar2(15), STUDENT_NUMBER int
     , CURRENT_GRADE_LEVEL int
     , CURRENT_SCHOOL_ABBREVIATION varchar2(3)
     , GENDER varchar2(1)
     , ETHNICITY_NAME varchar2(4), ETHNICITY_CODE int
     , SPECIAL_ED_STUDENT varchar2(2), ID int, STUDENTID int, SCHOOLID int
     , ATT_DATE timestamp, ATTENDANCE_CODEID int, ATT_CODE varchar2(3)
     , ATT_MODE_CODE varchar2(15), ATT_INTERVAL int, CALENDAR_DAYID int
     , CCID int, ATT_COMMENT int, CC_SCHOOLID int, DROPPED int, PERIODID int
     , PERIOD_ABBREVIATION varchar2(2), PERIOD_NUMBER int, SECTIONID int
     , SECTION_NUMBER int, PROGRAMID int, PROGRAM_NAME int, TRACK_A int
     , TRACK_B int, TRACK_C int, TRACK_D int, TRACK_E int, TRACK_F int
     , INSESSION int, COUNT_FOR_ADA int, PRESENCE_STATUS_CD varchar2(6)
     , CYCLE_DAY_ID int, CYCLE_DAY_ABBREVIATION varchar2(2), TOTAL_MINUTES int)
;

INSERT ALL 
    INTO PSSIS_ATTENDANCE_MEETING (NAME, STUDENT_NUMBER, CURRENT_GRADE_LEVEL, CURRENT_SCHOOL_ABBREVIATION, GENDER, ETHNICITY_NAME, ETHNICITY_CODE, SPECIAL_ED_STUDENT, ID, STUDENTID, SCHOOLID, ATT_DATE, ATTENDANCE_CODEID, ATT_CODE, ATT_MODE_CODE, ATT_INTERVAL, CALENDAR_DAYID, CCID, ATT_COMMENT, CC_SCHOOLID, DROPPED, PERIODID, PERIOD_ABBREVIATION, PERIOD_NUMBER, SECTIONID, SECTION_NUMBER, PROGRAMID, PROGRAM_NAME, TRACK_A, TRACK_B, TRACK_C, TRACK_D, TRACK_E, TRACK_F, INSESSION, COUNT_FOR_ADA, PRESENCE_STATUS_CD, CYCLE_DAY_ID, CYCLE_DAY_ABBREVIATION,TOTAL_MINUTES)
         VALUES ('used_by_already', 999999, 1, 'OHS', 'F', NULL, 6, 'No', 7240947, 40576, 280100, '14-Dec-2017 12:00:00 AM', 4345, 'EXA', 'ATT_ModeMeeting', 0, 97488, 790700, NULL, 280100, 0, 5731, 'AM', 1, 66373, 1, 0, NULL, 1, 1, 1, 1, 1, 1, 1, 1, 'Absent', 3214, 'TH', 0)
    INTO PSSIS_ATTENDANCE_MEETING (NAME, STUDENT_NUMBER, CURRENT_GRADE_LEVEL, CURRENT_SCHOOL_ABBREVIATION, GENDER, ETHNICITY_NAME, ETHNICITY_CODE, SPECIAL_ED_STUDENT, ID, STUDENTID, SCHOOLID, ATT_DATE, ATTENDANCE_CODEID, ATT_CODE, ATT_MODE_CODE, ATT_INTERVAL, CALENDAR_DAYID, CCID, ATT_COMMENT, CC_SCHOOLID, DROPPED, PERIODID, PERIOD_ABBREVIATION, PERIOD_NUMBER, SECTIONID, SECTION_NUMBER, PROGRAMID, PROGRAM_NAME, TRACK_A, TRACK_B, TRACK_C, TRACK_D, TRACK_E, TRACK_F, INSESSION, COUNT_FOR_ADA, PRESENCE_STATUS_CD, CYCLE_DAY_ID, CYCLE_DAY_ABBREVIATION,TOTAL_MINUTES)
         VALUES ('used_by_already', 999999, 1, 'OHS', 'F', NULL, 6, 'No', 7240948
                 , 40576, 280100, '14-Dec-2017 12:00:00 AM', 4345
                 , 'EXA', 'ATT_ModeMeeting', 0, 97488, 790696, NULL
                 , 280100, 0, 5732, 'PM', 2, 66427, 1, 0, NULL
                 , 1, 1, 1, 1, 1, 1, 1, 1, 'Absent', 3214, 'TH'
                 , 0)
SELECT * FROM dual
;

查询1

      SELECT
              attm.studentid
            , attm.period_number
            , listagg(attm.att_code,'|') within group (order by attm.att_code) attcodes
      FROM pssis_attendance_meeting attm 
      WHERE attm.att_date=to_date('14-Dec-2017') 
      AND attm.att_code IS NOT NULL 
      GROUP BY
              attm.studentid
            , attm.period_number
;

<强> Results

| STUDENTID | PERIOD_NUMBER | ATTCODES |
|-----------|---------------|----------|
|     40576 |             1 |      EXA |
|     40576 |             2 |      EXA |

查询2

SELECT
        studentid
      , max(case when period_number='1'  then attcodes end) per1
      , max(case when period_number='2'  then attcodes end) per2
      , max(case when period_number='3'  then attcodes end) per3
      , max(case when period_number='4'  then attcodes end) per4
      , max(case when period_number='5'  then attcodes end) per5
      , max(case when period_number='6'  then attcodes end) per6
      , max(case when period_number='7'  then attcodes end) per7
      , max(case when period_number='8'  then attcodes end) per8
      , max(case when period_number='9'  then attcodes end) per9
      , max(case when period_number='10' then attcodes end) per10
FROM (
      SELECT
              attm.studentid
            , attm.period_number
            , listagg(attm.att_code,'|') within group (order by attm.att_code) attcodes
      FROM pssis_attendance_meeting attm 
      WHERE attm.att_date=to_date('14-Dec-2017') 
      AND attm.att_code IS NOT NULL 
      GROUP BY
              attm.studentid
            , attm.period_number
      ) d
GROUP BY
        studentid

<强> Results

| STUDENTID | PER1 | PER2 |   PER3 |   PER4 |   PER5 |   PER6 |   PER7 |   PER8 |   PER9 |  PER10 |
|-----------|------|------|--------|--------|--------|--------|--------|--------|--------|--------|
|     40576 |  EXA |  EXA | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) |

答案 1 :(得分:0)

感谢您的耐心等待!我的下面的查询旨在为参加活动/体育活动的学生提供所有时段的出勤率。现在我只想在一个或多个时段内缺席时显示记录。我尝试添加attm.att_code IS NOT NULL但我无法找到一种方法在所有时段都这样做,所以显然不起作用。我可以为参加多项运动/活动的学生获得多行,但两行的出勤率相同。

我还想通过体育/活动对出席情况进行分组,但是当我在查询结束时添加GROUP BY co.course_name时,它也无法正常工作。

SELECT DISTINCT 
      s.student_number AS "Student Number", 
      s.lastfirst AS "Student Name", 
      DECODE(s.grade_level,-1,'PK',0,'KG',s.grade_level) AS "Grade", 
      s.home_phone AS "Phone", 
      DECODE(s.schoolid,280050,'Kodiak High School',s.schoolid) AS "School",
      (SELECT DISTINCT co.course_name FROM ps.courses WHERE co.course_number=se.course_number AND se.course_number LIKE 'CLB%' OR se.course_number LIKE 'ACT%') AS "Course",
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='1') AS "Per. 1", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='2') AS "Per. 2", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='3') AS "Per. 3", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='4') AS "Per. 4", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='5') AS "Per. 5", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='6') AS "Per. 6", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='7') AS "Per. 7", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='8') AS "Adv", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='9') AS "Act", 
      (SELECT listagg(attm.att_code,'|') within group (order by attm.att_code) FROM pssis_attendance_meeting attm WHERE attm.att_date=to_date(SYSDATE) AND attm.studentid=s.id AND attm.att_code IS NOT NULL AND attm.period_number='10') AS "Clb" 

      FROM attendance att
      JOIN students s ON s.id=att.studentid
      INNER JOIN cc ON s.ID=cc.studentid 
      INNER JOIN sections se ON cc.sectionid = se.id
      JOIN courses co ON co.course_number=se.COURSE_NUMBER

      WHERE att.att_date=to_date(SYSDATE) 
      AND att.schoolid in '280050'
      AND s.enroll_status=0 
      AND cc.termid = 2700 
      AND se.course_number LIKE 'ACT%'OR se.course_number LIKE 'CLB%'


      ORDER BY s.lastfirst

答案 2 :(得分:0)

显然你不明白我的想法。拿我提供的提出新查询看起来有点像这样:

SELECT
      s.*, att.* --  choose which columns you want, form these sources or other you can add to it
from students AS s
INNER JOIN (
            SELECT
                    studentid
                  , max(case when period_number='1'  then attcodes end) per1
                  , max(case when period_number='2'  then attcodes end) per2
                  , max(case when period_number='3'  then attcodes end) per3
                  , max(case when period_number='4'  then attcodes end) per4
                  , max(case when period_number='5'  then attcodes end) per5
                  , max(case when period_number='6'  then attcodes end) per6
                  , max(case when period_number='7'  then attcodes end) per7
                  , max(case when period_number='8'  then attcodes end) per8
                  , max(case when period_number='9'  then attcodes end) per9
                  , max(case when period_number='10' then attcodes end) per10
            FROM (
                  SELECT
                          attm.studentid
                        , attm.period_number
                        , listagg(attm.att_code,'|') within group (order by attm.att_code) attcodes
                  FROM pssis_attendance_meeting attm 
                  WHERE attm.att_date=to_date('14-Dec-2017') 
                  AND attm.att_code IS NOT NULL 
                  GROUP BY
                          attm.studentid
                        , attm.period_number
                  ) d
            GROUP BY
                    studentid
      ) AS att on s.studentid = att.studentid

您可以在任何地方选择所需的列,但如果您使用我给您的子查询,则使用INNER JOIN它将解决&#34; not null&#34;问题。

请告诉我你现在明白了。

答案 3 :(得分:0)

SELECT
         s.student_number AS "Student Number"
       , s.lastfirst AS "Student Name"
       , DECODE(s.grade_level, - 1, 'PK', 0, 'KG', s.grade_level) AS "Grade"
       , s.home_phone AS "Phone"
       , DECODE(s.schoolid, 280050, 'Kodiak High School', s.schoolid) AS "School"
       , att.*
FROM (
            SELECT
                    studentid
                  , max(case when period_number='1'  then attcodes end) per1
                  , max(case when period_number='2'  then attcodes end) per2
                  , max(case when period_number='3'  then attcodes end) per3
                  , max(case when period_number='4'  then attcodes end) per4
                  , max(case when period_number='5'  then attcodes end) per5
                  , max(case when period_number='6'  then attcodes end) per6
                  , max(case when period_number='7'  then attcodes end) per7
                  , max(case when period_number='8'  then attcodes end) per8
                  , max(case when period_number='9'  then attcodes end) per9
                  , max(case when period_number='10' then attcodes end) per10
            FROM (
                  SELECT
                          attm.studentid
                        , attm.period_number
                        , listagg(attm.att_code,'|') within group (order by attm.att_code) attcodes
                  FROM pssis_attendance_meeting attm 
                  WHERE attm.att_date=trunc(sysdate)
                  AND attm.att_code IS NOT NULL 
                  AND attm.schoolid IN '280050'
                  GROUP BY
                          attm.studentid
                        , attm.period_number
                  ) d
            GROUP BY
                    studentid
     ) att
INNER JOIN students s ON s.id = att.studentid
INNER JOIN cc ON s.ID = cc.studentid
INNER JOIN sections se ON cc.sectionid = se.id
INNER JOIN courses co ON co.course_number = se.COURSE_NUMBER
WHERE s.enroll_status = 0 AND cc.termid = 2700 AND se.course_number LIKE 'ACT%' OR se.course_number LIKE 'CLB%'
ORDER BY s.lastfirst