根据得分和名称

时间:2016-12-20 17:49:21

标签: mysql sql

我有一个分数列表,想要输出用户的排名。我使用的代码为具有相同分数的用户输出相同的排名,而我需要每个用户的唯一排名(按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)

9 个答案:

答案 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

Example

为所有用户排名

您的问题有点令人困惑,似乎没有人确定您是否需要特定用户的排名或所有用户的列表。所以这是我的清单解决方案:

SELECT
    uid,
    userName,
    pts,
    @curRank := @curRank + 1 AS rank
FROM
    tbl_users
CROSS JOIN (SELECT @curRank := 0) AS rank
ORDER BY
    pts DESC,
    userName;

Example

答案 3 :(得分:1)

使用排名查询和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);
}

如果您的表中有大量行,请注意此查询可能很慢。

其他选项

还有其他一些涉及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

SQL Fiddle

上查看

答案 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;