This question询问如何按用户ID选择用户的排名。
id name points
1 john 4635
3 tom 7364
4 bob 234
6 harry 9857
接受的答案是
SELECT uo.*,
(
SELECT COUNT(*)
FROM users ui
WHERE (ui.points, ui.id) >= (uo.points, uo.id)
) AS rank
FROM users uo
WHERE id = @id
这是有道理的。我想了解这种方法之间的性能权衡,或者通过修改数据库结构来存储计算的排名(我想每次排名变化时需要进行大量更改),或任何其他方法太想新闻了。我是db noob。
答案 0 :(得分:1)
性能权衡基本上与您所描述的相同:
如果您修改了结构以存储排名,那么查询将非常,非常简单和快速。但是,这会在任何时候“点”发生变化时需要一些开销,因为你必须验证排名没有改变。如果排名发生了变化,您必须进行多次更新。
这会在每次更新/插入时导致更多工作(可能存在错误)。权衡是非常快速的读取。如果您的典型用法是与数百万次读取相比很少的修改,并且您发现此查询是瓶颈,则可能值得考虑重新处理此问题。但是,除非您真正发现这是一个问题,否则我会避免增加复杂性和可维护性问题,因为当前的解决方案需要更少的存储空间,并且非常灵活。
答案 1 :(得分:1)
您引用的链接是MySQL问题。如果原始数据库是Oracle,那么接受的答案就是使用一个分析函数,它可以很好地扩展:
SQL> select id, name, points from users order by id
2 /
ID NAME POINTS
---------- ---------- ----------
1 john 4635
3 tom 7364
4 bob 234
6 harry 9857
8 algernon 1
9 sebastian 234
10 charles 888
7 rows selected.
SQL> select name, id, points, rank() over (order by points)
2 from users
3 /
NAME ID POINTS RANK()OVER(ORDERBYPOINTS)
---------- ---------- ---------- -------------------------
algernon 8 1 1
bob 4 234 2
sebastian 9 234 2
charles 10 888 4
john 1 4635 5
tom 3 7364 6
harry 6 9857 7
7 rows selected.
SQL> select name, id, points, dense_rank() over (order by points desc)
2 from users
3 /
NAME ID POINTS DENSE_RANK()OVER(ORDERBYPOINTSDESC)
---------- ---------- ---------- -----------------------------------
harry 6 9857 1
tom 3 7364 2
john 1 4635 3
charles 10 888 4
bob 4 234 5
sebastian 9 234 5
algernon 8 1 6
7 rows selected.
SQL>
答案 2 :(得分:0)
该查询的“where”部分内部是否需要读取整个表?我理解过早优化。在学术上,似乎这不会超过几千行。