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'
很可能您当前正在使用 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 行),则将类型移至这些索引中的第一个位置。
我有一个像这样的 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'
很可能您当前正在使用 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 行),则将类型移至这些索引中的第一个位置。