Ranking with ties and skipping certain rows where one condition is not met in mysql

StackOverflow https://stackoverflow.com/questions/20369357

  •  29-08-2022
  •  | 
  •  

I have been googling since yesterday on how I could do this but with no avail. I can perfectly achieve ranking with ties and return rank of a specific student using php and mysql quesry. But I have one problem. The problem is that if a student fails in one subject (pass mark is given 33) out of group by subject (available different subjects) in the table, I want to skip calculating his ranking using mysql.

$query = "SELECT id, Names, 
TOTALSCORE, Rank
FROM(
(SELECT t.*, IF(@p = TOTALSCORE, @n, @n := @n + 1)  
AS Rank, @p := TOTALSCORE
FROM(
(SELECT id, Names,
SUM(score) TOTALSCORE
FROM exam, (SELECT @n := 0, @p := 0) n
GROUP BY id
ORDER BY TOTALSCORE DESC
) t
) r";
$myrank = mysql_query($query, $dbconnect) or die(mysql_error());        
$i = 0;
$j = 0;
$data = array();
while($row_myrank = mysql_fetch_assoc($myrank)){
$data[$i] = $row_myrank;
if(isset($data[$i - 1]) && $data[$i - 1]['TOTALSCORE'] == $data[$i]['TOTALSCORE']){
$data[$i]['Rank'] = $j;
}else{
$data[$i]['Rank'] = ++$j;
    }
$i++;
}
foreach($data as $key => $value){
 if($value['id'] == $id){
   if($value['Rank']>0){
   return $value['Rank'];
  } else{
       return "<font color=red>Not get Ranking.</font>";
 }
}
} 

This is the sample shot of what I want to achieve. In this shot, I only have three different students, in the application I might have more than 300 different students. The subject where a student failed is marked red. ranking

有帮助吗?

解决方案

I am not quite sure what "pass mark is given 33" means.

I assume that it is 33% of Fullmark,
for example if Fullmark=75 then the pass score is 33% of 75 = 24,75 points,
which means that a student must gain at least 24,75 points to pass the exam.

In this case a simple check with an antijoin can help:

WHERE NOT EXISTS(
  SELECT null FROM exam e
  WHERE e.id = r.id
    AND e.score/e.Fullmark < 0.33
);

the above means: "give me only these records for which does not exist any exam with pas mark < 33%"

A full query is shown below, and a demo here --> http://www.sqlfiddle.com/#!2/50ef8/2

SELECT id, Names, TOTALSCORE, Rank
FROM
(  
   SELECT t.*, 
         IF(@p = TOTALSCORE, @n, @n := @n + 1) AS Rank, 
         @p := TOTALSCORE
   FROM(
     SELECT id, Names,SUM(score) TOTALSCORE
         FROM exam, (SELECT @n := 0, @p := 0) n
         GROUP BY id
         ORDER BY TOTALSCORE DESC
   ) t
) r
WHERE NOT EXISTS(
  SELECT null FROM exam e
  WHERE e.id = r.id
    AND e.score/e.Fullmark < 0.33
);



-- EDIT -- The above query calculates incorrect rank values, here is improved version:

SELECT id, Names, TOTALSCORE, Rank
FROM
(  
   SELECT t.*, 
         IF(@p = TOTALSCORE, @n, @n := @n + 1) AS Rank, 
         @p := TOTALSCORE
   FROM(
     SELECT id, Names,SUM(score) TOTALSCORE
         FROM exam e1, (SELECT @n := 0, @p := 0) n
         WHERE NOT EXISTS(
            SELECT null FROM exam e2
            WHERE e1.id = e2.id
            AND e2.score/e2.Fullmark < 0.33
          )
         GROUP BY id
         ORDER BY TOTALSCORE DESC
   ) t
) r
;

and demo: --> http://www.sqlfiddle.com/#!2/50ef8/4

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top