PASS和FAIL记录相同的测试

时间:2018-05-23 13:56:00

标签: mysql sql

SQL新手在这里。我尝试过搜索,但无法找到这种情况。

对于特定考试,学生可以有多个记录(通过,失败,未显示,丢弃)。

results table

Student_ID  Exam_ID    Status     Time_stamp

   1          A       Passed      2018-05-01
   2          A       Failed      2018-05-01
   2          A       Passed      2018-05-05  
   3          A       No-Show     2018-05-01
   3          A       Failed      2018-05-05
   4          A       Passed      2018-05-01
   4          A       Failed      2018-05-25

如何构建我的SQL查询以显示已提交的学生列表,如果他们没有通过,则按日期显示最新状态。

例如,在示例数据中,student_id 1 =已通过,student_id 2 =已通过(一次通过记录=已通过)且student_id 3 =已失败(未通过记录,未通过后未通过),student_id 4 =已通过(一次通过)记录考试=通过,忽略以后失败)

到目前为止,我已尝试过这个 -

SELECT * 
FROM results
WHERE Status = "Passed"

但这显然不包括未通过的状态。

真的很感激帮助。

4 个答案:

答案 0 :(得分:1)

以下是使用union all的一种方法:

select r.*
from results r
where r.status = 'Passed'
union all
select t.*
from results r
where not exists (select 1 
                  from results r2
                  where r2.student_id = r.student_id and
                        r2.exam_id = r.exam_id and
                        r2.status = 'Passed'
                 ) and
      r.time_stamp = (select max(r2.time_stamp
                      from results r2
                      where r2.student_id = r.student_id and
                            r2.exam_id = r.exam_id 
                     );

答案 1 :(得分:0)

以下链接几乎相同。使用一些策略,你会得到你的答案

SQL query to find a specific value for all records

答案 2 :(得分:0)

您也可以使用RANK:

执行此操作
SELECT student_id, exam_id, status, time_stamp
FROM
(
SELECT *, RANK() OVER(PARTITION BY student_id ORDER BY time_stamp DESC) AS rnk
FROM t
) sub
WHERE status = 'Passed'
OR (rnk = 1
    AND NOT EXISTS
    (SELECT 1
     FROM t t2
     WHERE status = 'Passed'
     AND t2.student_id = sub.student_id))

所以逻辑是:记录状态通过的记录或(1)测试是学生最近的测试和(2)学生没有通过考试。

答案 3 :(得分:0)

优化版

with t (Student_ID, Exam_ID, Status, Time_stamp) as ( select 1, 'A', 'Passed', '2018-05-01' union all select 2, 'A', 'Failed', '2018-05-01' union all select 2, 'A', 'Passed', '2018-05-05' union all select 3, 'A', 'No-Show', '2018-05-01' union all select 3, 'A', 'Failed', '2018-05-05' union all select 4, 'A', 'Passed', '2018-05-01' union all select 4, 'A', 'Failed', '2018-05-25') select * from (select *,row_number() over(PARTITION BY student_id,exam_id order by case when status='Passed' then 1 when status='Failed' then 2 when status='No-Show' then 3 end, time_stamp desc) r from t) result where r=1