2

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 = failed(无通过记录,失败后未出现),student_id 4 = 通过(一条通过记录在考试=通过,稍后忽略失败)

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

SELECT * 
FROM results
WHERE Status = "Passed"

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

非常感谢您的帮助。

4

4 回答 4

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 
                     );
于 2018-05-23T14:10:03.023 回答
1

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

为所有记录查找特定值的 SQL 查询

于 2018-05-23T14:19:28.357 回答
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

于 2018-05-23T16:08:27.373 回答
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)学生没有通过测试。

于 2018-05-23T14:32:52.870 回答