SQL 用户评分分组排名
SQL User Score ranking by grouping
我有以下排名系统。
SET @1=0;
SELECT id, username, magic_xp, @i:=@i+1 AS rank
FROM hs_users
ORDER
BY magic_xp DESC;
hs_users
id username magic_xp rank
988 5hapescape 14926854 1
737 Ozan 13034431 2
989 Kurt 13034431 3
6 LEGACY 0 4
11 Bobby 0 5
276 Bobby123 0 6
345 Mynamesjason 0 7
450 Demon Spawn 0 8
987 Satan 0 9
如您所见,我有 2 个用户拥有相同的 xp。
我想让它们都具有 rank = 2
,其余的应该遵循 3
。
我怎样才能像这样对它们进行分组?
| username | magic_xp | rank |
| ---------- + -------- + ---- |
| ShapeScape | 1000 | 1 |
| Kurt | 100 | 2 |
| Ozan | 100 | 2 |
| Legacy | 10 | 3 |
查询
set @i := 0;
set @lagxp := null;
select id, username, magic_xp,
@i := if(@lagxp = magic_xp, @i,
if(@lagxp := magic_xp, @i + 1, @i + 1)) as rank
from hs_users
order by magic_xp desc
;
或
SELECT id, username, magic_xp,
IF (@score=hs_users.magic_xp, @rank:=@rank, @rank:=@rank+1) as rank,
@score:=hs_users.magic_xp score
FROM hs_users, (SELECT @score:=0, @rank:=0) r
ORDER BY magic_xp DESC;
输出
+-----+------------+----------+------+----------+
| id | username | magic_xp | rank | lagxp |
+-----+------------+----------+------+----------+
| 988 | Shapescape | 14926894 | 1 | 14926894 |
| 737 | Ozan | 13034431 | 2 | 13034431 |
| 989 | Kurt | 13034431 | 2 | 13034431 |
| 6 | Legacy | 0 | 3 | 0 |
+-----+------------+----------+------+----------+
在MySQL中,最高效的方法是使用变量:
select t.*,
(@rank := if(@magic_xp = magic_xp, @rank,
if(@magic_xp := magic_xp, @rank + 1, @rank + 1)
)
) as rank
from table t cross join
(select @rank := 0, @magic_xp := NULL) params
order by magic_xp desc;
注意变量的复杂表达式。两个变量的赋值都在一个表达式中。这是故意的。 MySQL 不保证 SELECT
中表达式的赋值顺序,有时甚至不按顺序求值。单个表达式是执行此逻辑的安全方法。
SQL 中更标准的方法是使用相关子查询:
select t.*,
(select count(distinct t2.magic_xp)
from table t2
where t2.magic_xp >= t.magic_xp
) as rank
from table t;
提出解决方案:)
SELECT id, username, magic_xp,
IF (@score=hs_users.magic_xp, @rank:=@rank, @rank:=@rank+1) as rank,
@score:=hs_users.magic_xp score
FROM hs_users, (SELECT @score:=0, @rank:=0) r
ORDER BY magic_xp DESC;
感谢@amdixon
select
@rank:=if(magic_xp=@prev_magic_xp,@rank,@rank+1) as rank,
username,
magic_xp,
@prev_magic_xp:=magic_xp as prev_magic_xp
from user,(select @rank:=0,@prev_magic_xp="") t
order by magic_xp desc
我有以下排名系统。
SET @1=0;
SELECT id, username, magic_xp, @i:=@i+1 AS rank
FROM hs_users
ORDER
BY magic_xp DESC;
hs_users
id username magic_xp rank
988 5hapescape 14926854 1
737 Ozan 13034431 2
989 Kurt 13034431 3
6 LEGACY 0 4
11 Bobby 0 5
276 Bobby123 0 6
345 Mynamesjason 0 7
450 Demon Spawn 0 8
987 Satan 0 9
如您所见,我有 2 个用户拥有相同的 xp。
我想让它们都具有 rank = 2
,其余的应该遵循 3
。
我怎样才能像这样对它们进行分组?
| username | magic_xp | rank |
| ---------- + -------- + ---- |
| ShapeScape | 1000 | 1 |
| Kurt | 100 | 2 |
| Ozan | 100 | 2 |
| Legacy | 10 | 3 |
查询
set @i := 0;
set @lagxp := null;
select id, username, magic_xp,
@i := if(@lagxp = magic_xp, @i,
if(@lagxp := magic_xp, @i + 1, @i + 1)) as rank
from hs_users
order by magic_xp desc
;
或
SELECT id, username, magic_xp,
IF (@score=hs_users.magic_xp, @rank:=@rank, @rank:=@rank+1) as rank,
@score:=hs_users.magic_xp score
FROM hs_users, (SELECT @score:=0, @rank:=0) r
ORDER BY magic_xp DESC;
输出
+-----+------------+----------+------+----------+
| id | username | magic_xp | rank | lagxp |
+-----+------------+----------+------+----------+
| 988 | Shapescape | 14926894 | 1 | 14926894 |
| 737 | Ozan | 13034431 | 2 | 13034431 |
| 989 | Kurt | 13034431 | 2 | 13034431 |
| 6 | Legacy | 0 | 3 | 0 |
+-----+------------+----------+------+----------+
在MySQL中,最高效的方法是使用变量:
select t.*,
(@rank := if(@magic_xp = magic_xp, @rank,
if(@magic_xp := magic_xp, @rank + 1, @rank + 1)
)
) as rank
from table t cross join
(select @rank := 0, @magic_xp := NULL) params
order by magic_xp desc;
注意变量的复杂表达式。两个变量的赋值都在一个表达式中。这是故意的。 MySQL 不保证 SELECT
中表达式的赋值顺序,有时甚至不按顺序求值。单个表达式是执行此逻辑的安全方法。
SQL 中更标准的方法是使用相关子查询:
select t.*,
(select count(distinct t2.magic_xp)
from table t2
where t2.magic_xp >= t.magic_xp
) as rank
from table t;
提出解决方案:)
SELECT id, username, magic_xp,
IF (@score=hs_users.magic_xp, @rank:=@rank, @rank:=@rank+1) as rank,
@score:=hs_users.magic_xp score
FROM hs_users, (SELECT @score:=0, @rank:=0) r
ORDER BY magic_xp DESC;
感谢@amdixon
select
@rank:=if(magic_xp=@prev_magic_xp,@rank,@rank+1) as rank,
username,
magic_xp,
@prev_magic_xp:=magic_xp as prev_magic_xp
from user,(select @rank:=0,@prev_magic_xp="") t
order by magic_xp desc