[英]How do I assign same rank to users with the same score with PHP?
$check_res = $con->query(
"SELECT *
FROM `results`
WHERE school_session='$session'
AND Term='$term'
AND class='$class'
AND subjectID='$subjectID'
ORDER BY Average DESC ");
$score_ends = array(1 => "st", 2 => "nd", 3 => "rd", 4 => "th");
$key_counter=1;
foreach ($check_res as $value) {
$key_counters=$key_counter++;
if($RegNum == $value['StudentReg']){
if($key_counters < 4){
echo $key_counters.$score_ends[$key_counters];
}else{
echo $key_counters.$score_ends[4];
}
}
}
此处的代码根据平均对用户进行排名。 它的工作正常。 但它不会为平均得分相同的用户分配相同的排名。 例如 20-1 日 20-2 日
但我想要的是这个 20-1st 20-1st 21-3rd
如果您运行的是 MySQL 8.0,则可以使用窗口函数直接在数据库中进行排名:
select r.*, rank() over(order by average desc) rn
from results r
where
school_session = ?
and term = ?
and class = ?
and subjectid = ?
order by average desc
rank()
为关系分配相同的数字。
请注意,我将查询更改为使用参数,而不是在查询字符串中连接 php 变量:这既安全又高效。
因此,您的代码中有一些不是最佳实践或有点令人困惑的地方。
prepared
语句。 它们在使用用户派生数据时提供更好的保护(不清楚您的搜索参数是来自用户输入还是来自其他代码)$variables
,最好使用{curly braces}
来包含它们。 它使用正确的变量解决了PHP
的各种问题,也使其更易于阅读和维护$Reg
来源 - 所以我在下面的代码中忽略了它假设您的表中有以下数据...
表:结果
StudentReg | school_session | Term | class | subjectID | Average
-----------+---------------+------+-------+-----------+-------------
1 | 1022 | 3 | 37 | 66 | 121
2 | 1022 | 3 | 37 | 66 | 115
3 | 1022 | 3 | 37 | 66 | 129
4 | 1022 | 3 | 37 | 66 | 121
5 | 1022 | 3 | 37 | 66 | 121
6 | 1022 | 3 | 37 | 66 | 117
7 | 1022 | 3 | 37 | 66 | 129
8 | 1022 | 3 | 37 | 66 | 125
9 | 1022 | 3 | 37 | 66 | 120
10 | 1022 | 3 | 37 | 66 | 118
11 | 1022 | 3 | 37 | 66 | 125
12 | 1022 | 3 | 37 | 66 | 124
13 | 1022 | 3 | 37 | 66 | 125
14 | 1022 | 3 | 37 | 66 | 125
查询返回的排序数据
StudentReg | school_session | Term | class | subjectID | Average
-----------+---------------+------+-------+-----------+-------------
2 | 1022 | 3 | 37 | 66 | 115
6 | 1022 | 3 | 37 | 66 | 117
10 | 1022 | 3 | 37 | 66 | 118
9 | 1022 | 3 | 37 | 66 | 120
1 | 1022 | 3 | 37 | 66 | 121
5 | 1022 | 3 | 37 | 66 | 121
4 | 1022 | 3 | 37 | 66 | 121
8 | 1022 | 3 | 37 | 66 | 125
12 | 1022 | 3 | 37 | 66 | 124
11 | 1022 | 3 | 37 | 66 | 125
13 | 1022 | 3 | 37 | 66 | 125
14 | 1022 | 3 | 37 | 66 | 125
3 | 1022 | 3 | 37 | 66 | 129
7 | 1022 | 3 | 37 | 66 | 129
我已经修改了代码以使用prepared
语句。
变量
大概这些是在你的代码更远的地方声明的......
$session = 1022;
$term = 3;
$class = 37;
$subjectID = 66;
mysqli
// SQL query to SELECT "Average" and "StudentReg" from "results"
// ?s are a place holder for values we'll bind later
$sql = "
SELECT StudentReg, Average
FROM `results`
WHERE school_session = ?
AND Term = ?
AND class = ?
AND subjectID = ?
ORDER BY Average DESC
";
$query = $mysqli->prepare(); // Prepare the query
$query->bind_param("iiii", $session, $term, $class, $subjectID); // Bind search values to parameters ("iiii" : one "i" for each variable, set's data type to "int")
$query->execute(); // Run the query
$query->Store_result(); // Store the result set
$query->bind_result($studentreg, $average); // Bind returned rows to variables
$score_ends = array(1 => "st", 2 => "nd", 3 => "rd", 4 => "th");
$last_value = false; // Initialise last value of result set
### $counter = 0; // Initialise the counter
$rank = 0;
while($query->fetch()){ // Loop through the result set
### $counter++; // Increment the counter
### // "if" statement using ternary logic
### // Sets the rank as either the counter OR the previous rank if it's the same
### $rank = ($last_value == false || $last_value <> $average) ? $counter : $rank;
// "if" statement using ternary logic
// Pre-increments (++ before variable) rank if the Average is not the same as previous
// ...or leaves as is if it is the same
$rank = ($last_value == false || $last_value <> $average) ? ++$rank: $rank;
$end = ($rank > 3) ? $score_ends[4] : $score_ends[$rank]; // Sets the suffix to the rank using ternary logic
echo "{$rank}{$end} {$studentreg}<br>"; // Prints the result; e.g. 1st 2 {2 == the StudentReg, presumably you'll update that to be a name or something}
$last_value = $average; // Sets current average as last value ready for next loop
}
PDO
// SQL query to SELECT "Average" and "StudentReg" from "results"
// ?s are a place holder for values we'll bind later
$sql = "
SELECT StudentReg, Average
FROM `results`
WHERE school_session = ?
AND Term = ?
AND class = ?
AND subjectID = ?
ORDER BY Average DESC
";
$query = $PDO->prepare(); // Prepare the query
$query->execute([$session, $term, $class, $subjectID]); // Execute the query and bind variables to place holders
$score_ends = array(1 => "st", 2 => "nd", 3 => "rd", 4 => "th");
$last_value = false; // Initialise last value of result set
### $counter = 0; // Initialise the counter
$rank = 0;
while($query->fetch()){ // Loop through the result set
### $counter++; // Increment the counter
### // "if" statement using ternary logic
### // Sets the rank as either the counter OR the previous rank if it's the same
### $rank = ($last_value == false || $last_value <> $row["Average"]) ? $counter : $rank;
// "if" statement using ternary logic
// Pre-increments (++ before variable) rank if the Average is not the same as previous
// ...or leaves as is if it is the same
$rank = ($last_value == false || $last_value <> $row["Average"]) ? ++$rank: $rank;
$end = ($rank > 3) ? $score_ends[4] : $score_ends[$rank] ; // Sets the suffix to the rank using ternary logic
echo "{$rank}{$end} {$row["StudentReg"]}<br>"; // Prints the result; e.g. 1st 2 {2 == the StudentReg, presumably you'll update that to be a name or something}
$last_value = $row["Average"]; // Sets current average as last value ready for next loop
}
输出
1st 2
2nd 6
3rd 10
4th 9
5th 1
5th 5
5th 4
8th 8
9th 12
10th 11
10th 13
10th 14
13th 3
13th 7
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.