Mysql 基于分数和名称输出唯一排名(行号)

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

我有一个分数列表,想输出用户的排名。我使用的代码为得分相等的用户输出相同的排名,而我需要每个用户的唯一排名(按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)
请尝试以下查询:

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