Mysql 基于分数和名称输出唯一排名(行号)
我有一个分数列表,想输出用户的排名。我使用的代码为得分相等的用户输出相同的排名,而我需要每个用户的唯一排名(按pts排序,然后按用户名排序),如下所示:Mysql 基于分数和名称输出唯一排名(行号),mysql,sql,Mysql,Sql,我有一个分数列表,想输出用户的排名。我使用的代码为得分相等的用户输出相同的排名,而我需要每个用户的唯一排名(按pts排序,然后按用户名排序),如下所示: uid | userName | pts | rank ------------------------- 3 | Jimmy | 100 | 1 10 | Alex | 98 | 2 (because of userName) 8 | John | 98 | 3 6 | Pete
uid | userName | pts | rank
-------------------------
3 | Jimmy | 100 | 1
10 | Alex | 98 | 2 (because of userName)
8 | John | 98 | 3
6 | Peter | 96 | 4
以下是我正在使用的代码:
SELECT
COUNT(*) AS rank
FROM tbl_users
WHERE pts>=(SELECT pts FROM tbl_users WHERE userID=:uid)
请尝试以下查询:
SET @rank=0;
SELECT uid,
userName,
pts,
@rank := @rank+1 AS rank
FROM tbl_users
ORDER BY pts DESC,
userName
密切相关的是,但在您的情况下,您需要按多个列排序,以处理具有相同点数的用户
更新:
如果实际计算了points列,则此查询可能会起作用:
SET @rank=0;
SELECT uid,
userName,
COUNT(*) AS pts,
@rank := @rank+1 AS rank
FROM tbl_users
GROUP BY uid,
userName
ORDER BY pts DESC,
userName
请尝试以下查询:
SET @rank=0;
SELECT uid,
userName,
pts,
@rank := @rank+1 AS rank
FROM tbl_users
ORDER BY pts DESC,
userName
密切相关的是,但在您的情况下,您需要按多个列排序,以处理具有相同点数的用户
更新:
如果实际计算了points列,则此查询可能会起作用:
SET @rank=0;
SELECT uid,
userName,
COUNT(*) AS pts,
@rank := @rank+1 AS rank
FROM tbl_users
GROUP BY uid,
userName
ORDER BY pts DESC,
userName
你可能想调查一下
选择uid、userName和pts(按pts、userName排序)上的行号()作为排名
从tbl_用户处
您可能需要查看
选择uid、userName和pts(按pts、userName排序)上的行号()作为排名
从tbl_用户
您需要MariaDB 10.2的RANK()
或densite_-RANK()
。请参阅MariaDB 10.2的RANK()
或densite\u RANK()
。请参见(订购人仅用于显示)
(订购人仅用于显示目的)
查找用户的排名 您只需统计拥有
- 更好的分数
- 同样的分数,但是一个更好的名字
SELECT
main.*,
count(*) AS rank
FROM
tbl_users main
LEFT JOIN tbl_users AS comparison
ON (comparison.pts > main.pts)
OR (
comparison.pts = main.pts
AND comparison.userName <= main.userName
)
WHERE
main.uid = :uid
查找用户排名 您只需统计拥有
- 更好的分数
- 同样的分数,但是一个更好的名字
SELECT
main.*,
count(*) AS rank
FROM
tbl_users main
LEFT JOIN tbl_users AS comparison
ON (comparison.pts > main.pts)
OR (
comparison.pts = main.pts
AND comparison.userName <= main.userName
)
WHERE
main.uid = :uid
你可以试试这个
SELECT * FROM (SELECT * FROM tbl_users ORDER BY `userName` ASC) AS t GROUP BY `pts` order by `pts` DESC
你可以试试这个
SELECT * FROM (SELECT * FROM tbl_users ORDER BY `userName` ASC) AS t GROUP BY `pts` order by `pts` DESC
使用排名查询和PDO
在您的一些评论中,您提到您正在尝试使用PDO来执行查询,并且您需要找到特定用户的排名。要实现这一点,您需要使用外部查询对标准排名查询进行排序(与Tim在其答案中发布的内容差不多)
然后,我们需要回顾一下,PDO不支持在一次调用中执行多个语句。所以我们就这样做
$dbh = new PDO(...);
$n = 8; # some value that probably comes from GET or POST
$stmt = $dbh->prepare("SET @rank=0");
$stmt->execute();
$stmt = $dbh->prepare("SELECT * FROM (
SELECT uid,
userName,
pts,
@rank := @rank+1 AS rank
FROM tbl_users
ORDER BY pts DESC,
userName) AS a WHERE uid=?");
$stmt->bindParam(1,$n);
$stmt->execute();
while ($a = $stmt->fetch()) {
print_r($a);
}
请注意,如果表中有大量行,则此查询可能会很慢
其他选择
还有一些其他的解决方案涉及左连接、不等式比较和交叉连接。这些查询可能与当前查询一样慢,甚至比当前查询慢
RANK、DENSERANK和ROW_NUMBER函数仅在MariaDB 10.2以后版本中可用,在mysql的其他版本中不可用。不幸的是,使用排名查询和PDO
在您的一些评论中,您提到您正在尝试使用PDO来执行查询,并且您需要找到特定用户的排名。要实现这一点,您需要使用外部查询对标准排名查询进行排序(与Tim在其答案中发布的内容差不多)
然后,我们需要回顾一下,PDO不支持在一次调用中执行多个语句。所以我们就这样做
$dbh = new PDO(...);
$n = 8; # some value that probably comes from GET or POST
$stmt = $dbh->prepare("SET @rank=0");
$stmt->execute();
$stmt = $dbh->prepare("SELECT * FROM (
SELECT uid,
userName,
pts,
@rank := @rank+1 AS rank
FROM tbl_users
ORDER BY pts DESC,
userName) AS a WHERE uid=?");
$stmt->bindParam(1,$n);
$stmt->execute();
while ($a = $stmt->fetch()) {
print_r($a);
}
请注意,如果表中有大量行,则此查询可能会很慢
其他选择
还有一些其他的解决方案涉及左连接、不等式比较和交叉连接。这些查询可能与当前查询一样慢,甚至比当前查询慢
RANK、DENSERANK和ROW_NUMBER函数仅在MariaDB 10.2以后版本中可用,在mysql的其他版本中不可用。不幸的是,Mariadb 10.2.您能检查一下吗:
SET @rank=0;
SELECT uid, userName, pts, @rank := @rank+1 AS rank FROM tbl_users ORDER BY amount DESC;
你能查一下吗
SET @rank=0;
SELECT uid, userName, pts, @rank := @rank+1 AS rank FROM tbl_users ORDER BY amount DESC;
我知道答案已经被接受了,但我想我无论如何都会提供这个,只是为了好玩 仅仅因为某人的名字“更好”,就可以在相同的分数上超过其他人,这似乎是一种耻辱 以下允许相等点的相等秩:
set @rank := 0;
select RANK.rank, U.uid, U.userName, U.pts
from users U
join ( select P1.pts, min( @rank := @rank + 1 ) as rank
from ( select U1.pts from users U1 order by pts desc ) P1
group by P1.pts
) RANK
on RANK.pts = U.pts
order by RANK.rank, U.userName;
结果:
rank uid userName pts
1 3 Jimmy 100
2 10 Alex 98
2 8 John 98
4 6 Peter 96
我知道一个答案已经被接受了,但我想我无论如何都会提供这个,只是为了好玩 仅仅因为某人的名字“更好”,就可以在相同的分数上超过其他人,这似乎是一种耻辱 以下允许相等点的相等秩:
set @rank := 0;
select RANK.rank, U.uid, U.userName, U.pts
from users U
join ( select P1.pts, min( @rank := @rank + 1 ) as rank
from ( select U1.pts from users U1 order by pts desc ) P1
group by P1.pts
) RANK
on RANK.pts = U.pts
order by RANK.rank, U.userName;
结果:
rank uid userName pts
1 3 Jimmy 100
2 10 Alex 98
2 8 John 98
4 6 Peter 96
在上查看它似乎不起作用。也许这会输出一个列表,但我只需要当前用户的排名。@user1542894是一个计算列的点列,还是它真的存在于
tbl_users
表中(我假设后者)?是的,它们存在于表中。我仍然得到了这个错误:致命错误:未捕获的异常“PDOException”,消息“SQLSTATE[HY000]:General error”在。。。堆栈跟踪:#0…:PDOStatement->fetch(2)#1{main}
。如您所见,我正在使用PDO并通过fetch(PDO::fetch_ASSOC)获得结果
@user1542894那么也许你的PHP代码有问题。似乎每当我使用变量时,比如SET@rank=0代码>。这就是php,它与我介绍的代码配合得很好:$stmt=$user\u home->runQuery(//sql在这里)$stmt->execute(数组(“:uid”=>$uid))$isrank=$stmt->fetch(PDO::fetch_ASSOC)
另外,是否应该在某个地方有一个WHERE userID=:uid
子句,以便只显示当前用户的排名?似乎不起作用。也许这会输出一个列表,但我只需要当前用户的排名。@user1542894是一个计算列的点列,还是它真的存在于tbl_users
表中(我假设后者)?是的,它们存在于表中。我仍然得到了这个错误:致命错误:未捕获的异常“PDOException”,消息“SQLSTATE[HY000]:General error”在。。。堆栈跟踪:#0…:PDO语句->获取(2)#1