MySQL 如果多个用户具有相同的值,则查找特定用户的排名

MySQL to find rank of specific user if multiple users have same values

我有一个像这样的 table 可以统计不同类型的用户总数。

 CREATE TABLE IF NOT EXISTS `records` (
  `id` int(6) unsigned NOT NULL,
  `sub_id` varchar(200) NOT NULL,
  `count` int(11) unsigned NOT NULL,
  `type` int(1) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

INSERT INTO `records` (`id`, `sub_id`, `count`, `type`) VALUES
(1, 'asfand', 200, 1),
(2, 'saba', 70, 2),
(3, 'faisal', 250, 1),
(4, 'ali', 250, 1),
(5, 'khan', 100, 1),
(6, 'sidra', 150, 1),
(7, 'ayesha', 300, 1);

我只想获得特定 sub_id 对 type = 1 的排名。

所以让我按照最高计数分数按降序排列。

+----+--------+-------+------+------+
| id | sub_id | count | type | rank |
+====+========+=======+======+======+
| 7  | ayesha | 300   | 1    | 1    |
| 3  | faisal | 250   | 1    | 2    |
| 4  | ali    | 250   | 1    | 3    |
| 1  | asfand | 200   | 1    | 4    |
| 6  | sidra  | 150   | 1    | 5    |
| 5  | khan   | 100   | 1    | 6    |
+----+--------+-------+------+------+

我已经有一个查询 returns 上面的第二个 table,它工作正常。但我想获得特定用户的排名。

例如,如果我要查找 ayesha 的排名,则为 1。同样如果我想找到 asfand 的排名,它是 4.

但是当我试图找到 Faisal 的排名时,它 returns 2 并且类似地 ali,它 returns 相同的排名 ' 2'.

下面是我的查询,它对所有记录都工作正常,但是如果 2 个人的计数相同,那么它就不能正常工作,它返回 faisal 和 ali 的排名 2。

SELECT count(count)+1 AS rank 
FROM records WHERE count > (SELECT count FROM records WHERE sub_id= 'ali' and type = 1) 
AND type = 1 ORDER BY count DESC;

这是我的 sql fiddle,请注意我的每条记录都有超过 100 万行。

可以使用ROW_NUMBER()window等函数

SELECT q.rnk
  FROM ( SELECT ROW_NUMBER() OVER (ORDER BY `count` DESC, `id`) AS rnk,
                r.*
           FROM `records` AS r
          WHERE `type` = 1 ) AS q
 WHERE q.`sub_id` = 'ali' -- 'faisal'

Demo

很可能您当前正在使用 DENSE_RANK()RANK() 函数( 包括 ORDER BY count DESC),这些函数可能会产生与ROW_NUMBER()

您的想法不是对所有行进行排名,而是只计算您想要的行,这听起来不错。但是你的排名是不完整的,因为你在排名中只考虑了 count 列,而在平局的情况下你还想使用 id 列。 (你在你的请求评论中提到了这一点。)查询变得不那么可读了:

SELECT COUNT(r.count) AS rnk
FROM records r
WHERE r.type = 1
AND EXISTS
(
  SELECT *
  FROM records r2
  WHERE r2.type = 1
  AND r2.sub_id = 'ali'
  AND (r.count > r2.count OR (r.count = r2.count AND r.id <= r2.id))
);

为此我建议使用两个索引:

假设名称(sub_id)比类型更具有选择性(一般来说类型很少,但名称很多),可以提供这个索引来快速查找需要的行:

CREATE INDEX idx1 ON records (sub_id, type, count);

然后您想按计数列查找所有行,因此为此提供另一个索引。我再次假设计数列可能比类型列更具选择性。

CREATE INDEX idx1 ON records (count, type);

如果类型列恰好非常有选择性(例如 table 中有一百万行,但类型 1 只有 100 行),则将类型移至这些索引中的第一个位置。