我有这样一张桌子:
id name incidence placeRef
1 John 10 1
2 Ann 9 1
3 Paul 9 1
4 Carl 8 1
5 John 4 1
6 Ann 4 1
7 Paul 7 1
8 Carl 1 1
我想使用ordinal ranking method对这些进行排名。哪个会在我的表中添加等级:
id name incidence placeRef rank
1 John 10 1 1
2 Ann 9 1 2
3 Paul 9 1 2
4 Carl 8 1 4
5 John 4 1 2
6 Ann 4 1 2
7 Paul 7 1 1
8 Carl 1 1 4
如何实现这一目标?
N.B。我将回答我自己的问题,但想知道是否有人有任何更好的解决方案,因为它有点hacky;虽然我发现很多帖子都在为这种情况推荐黑客。
答案 0 :(得分:2)
您可以使用变量或相关子查询执行此操作。子查询方法如下所示:
select t.*,
(select 1 + count(t2.incidence)
from table t2
where t2.incidence > t.incidence
) as rank
from table t;
变量方法有点棘手,因为你必须记住具有给定值的匹配行的数量:
select t.*,
(@rn := if(@i = t.incidence, if(@cnt := @cnt + 1, @rn, @rn),
@cnt + if(@i := t.incidence, if(@cnt := 1, @rn, @rn), @rn)
)
) as rank
from table t cross join
(select @i := 0, @rn := 0, @cnt := 1) vars
order by incidence desc;
编辑:
如果您想更新表格,只需将update
与join
一起使用:
update table t join
(<either subquery above>) s
on t.id = s.id
set t.rank = s.rank;
答案 1 :(得分:1)
以下作品:
UPDATE names
JOIN ( SELECT * FROM names ORDER BY placeRef, incidence DESC ) AS p ON p.id = names.id,
( SELECT @curRank := 0, @nextRank := 0, @prevInc := 9999999999, @prevPlace := 0 ) AS v
SET
names.rank = IF( @prevPlace != p.placeRef, @curRank := 0, 0 ),
names.rank = IF( @prevPlace != p.placeRef, @nextRank := 0, 0 ),
names.rank = IF( @prevInc = p.incidence, @nextRank := @nextRank + 1, @curRank := @nextRank := @nextRank + 1 ),
names.rank = IF( @prevInc = p.incidence, @curRank := @curRank, @curRank := @nextRank ),
names.incidence = @prevInc := names.incidence,
names.placeRef = @prevPlace := names.placeRef;
说明:
UPDATE names
1 - 设置要更新的表
JOIN ( SELECT * FROM names ORDER BY placeRef, incidence DESC ) AS p ON p.id = names.id,
2 - 这使得虚拟表的结果有序,因此可以应用排名
( SELECT @curRank := 0, @nextRank := 0, @prevInc := 9999999999, @prevPlace := 0 ) AS v
3 - 这设置了一些变量,用于判断何时进行篡改和重置等级
names.rank = IF( @prevPlace != p.placeRef, @curRank := 0, 0 ),
4 - 当MySQL迭代到新的地方时,这是一个将当前等级重置为0的黑客
names.rank = IF( @prevPlace != p.placeRef, @nextRank := 0, 0 ),
5 - 当MySQL迭代到一个新的地方时,这是一个将下一个等级重置为0的黑客
names.rank = IF( @prevInc = p.incidence, @nextRank := @nextRank + 1, @curRank := @nextRank := @nextRank + 1 ),
6 - 当当前发病率与之前的发病率相同时,这是一个更新下一个和当前等级的黑客
names.rank = IF( @prevInc = p.incidence, @curRank := @curRank, @curRank := @nextRank ),
7 - 当它的发生率与前一个相同时,它将等级设置为与最后一个等级相同,或者如果它不是
则增加等级names.incidence = @prevInc := names.incidence,
8 - 这是一个设置变量以包含先前发生率的hack,因此我们可以告诉下一次尝试该做什么
names.placeRef = @prevPlace := names.placeRef;
9 - 这是一个设置变量以包含前一个地方的黑客,所以我们可以告诉下一次尝试该做什么