Rookie SQL ici. J'ai essayé de chercher mais je n'ai pas trouvé ce scénario.

Pour un examen particulier, les étudiants peuvent avoir plusieurs enregistrements (réussite, échec, non-présentation, abandonné).

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

Comment puis-je structurer ma requête SQL pour afficher la liste des étudiants qui ont réussi et s'ils ne l'ont pas réussi, afficher le dernier statut par date.

Par exemple, dans les exemples de données Student_id 1 = Passé, Student_id 2 = Passé (un enregistrement de réussite = réussi) et Student_id 3 = Échoué (aucun enregistrement de réussite, un échec vient après une non-présentation), Student_id 4 = Passé (un enregistrement de réussite sur le examen = réussir, ignorer plus tard échouer)

Jusqu'à présent, j'ai essayé ceci -

SELECT * 
FROM results
WHERE Status = "Passed"

Mais cela n'inclut évidemment pas le statut de non passé.

J'apprécie vraiment l'aide.

1
Damon Daisley Wilson 23 mai 2018 à 16:55

4 réponses

Meilleure réponse

Voici une méthode utilisant 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
Gordon Linoff 23 mai 2018 à 14:10

Vous pouvez également le faire en utilisant 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))

La logique est donc la suivante: prenez les enregistrements où le statut est réussi OU (1) le test est le plus récent pour l'étudiant ET (2) l'étudiant n'a pas de test de réussite.

0
kjmerf 23 mai 2018 à 14:32

Une version optimisée

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

0
san 23 mai 2018 à 16:18

Le lien ci-dessous est presque le même. Utilisez quelques tactiques et vous obtiendrez votre réponse

Requête SQL pour trouver une valeur spécifique pour tous les enregistrements

0
pradeepTuran007 23 mai 2018 à 14:19