我有一个分数列表,想要输出用户的排名。我使用的代码为具有相同分数的用户输出相同的排名,而我需要每个用户的唯一排名(按pts排序,然后按用户名排序),如下所示:
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)
答案 0 :(得分:1)
尝试此查询:
SET @rank=0;
SELECT uid,
userName,
pts,
@rank := @rank+1 AS rank
FROM tbl_users
ORDER BY pts DESC,
userName
密切相关的是this SO question,但在您的情况下,您需要按多列排序以处理具有相同点数的用户。
<强>更新强>
如果实际计算了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
答案 1 :(得分:1)
(ORDER BY仅用于显示目的)
select u1.*
,(select count(*)
from tbl_users u2
where u2.pts > u1.pts
or ( u2.pts = u1.pts
and u2.userName <= u1.userName
)
) as rank
from tbl_users u1
order by rank
;
+-----+----------+-----+------+
| uid | userName | pts | rank |
+-----+----------+-----+------+
| 3 | Jimmy | 100 | 1 |
+-----+----------+-----+------+
| 10 | Alex | 98 | 2 |
+-----+----------+-----+------+
| 8 | John | 98 | 3 |
+-----+----------+-----+------+
| 6 | Peter | 96 | 4 |
+-----+----------+-----+------+
答案 2 :(得分:1)
寻找用户的排名
您只需计算拥有
的用户因此,您可以使用这些条件加入同一个表。
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
uid,
userName,
pts,
@curRank := @curRank + 1 AS rank
FROM
tbl_users
CROSS JOIN (SELECT @curRank := 0) AS rank
ORDER BY
pts DESC,
userName;
答案 3 :(得分:1)
在您的一些评论中,您提到过您正在尝试使用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);
}
如果您的表中有大量行,请注意此查询可能很慢。
还有其他一些涉及LEFT JOIN的解决方案,包括不等式比较和CROSS JOIN。这些可能与当前查询一样慢或甚至更慢。
RANK,DENSERANK和ROW_NUMBER函数仅在MariaDB 10.2之后可用,而在其他版本的mysql中不可用。不幸的是,Mariadb 10.2 isn't recommended for production。
答案 4 :(得分:1)
我知道答案已被接受,但我认为无论如何我都会提供这个答案,只是为了好玩。
有些人可能因为他们的名字更好而且#34;而有其他人可以用同样的分数来超过其他人,这似乎是一种耻辱。
以下允许相等等级的等级:
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
上查看
答案 5 :(得分:0)
您可能需要查看ROW_NUMBER()。
SELECT uid, userName, and pts, ROW_NUMBER() OVER (ORDER BY pts, userName) AS rank
FROM tbl_users
答案 6 :(得分:0)
您需要MariaDB 10.2的GET /devices/[Device ID]/messages/devicebound?api-version=2016-02-03 HTTP/1.1
Host: [IoTHubName].azure-devices.net
Authorization: SharedAccessSignature sr=[Shared Access Signature]
或RANK()
。见https://mariadb.com/kb/en/mariadb/rank/
答案 7 :(得分:0)
你可以试试这个
SELECT * FROM (SELECT * FROM tbl_users ORDER BY `userName` ASC) AS t GROUP BY `pts` order by `pts` DESC
答案 8 :(得分:0)
SET @rank=0;
SELECT uid, userName, pts, @rank := @rank+1 AS rank FROM tbl_users ORDER BY amount DESC;