Rails 请教一个 sql 的问题

tinyfeng · 2018年02月12日 · 最后由 tinyfeng 回复于 2018年02月12日 · 1260 次阅读

现在有一张 exam_result 表,表里有 user_id,score 字段,想要根据 score 进行排序,根据 page,per_page 返回用户以及排名,分数相同则排名相同(谁先谁后可以根据默认 id 排序,但是排名需要一样),我该怎么做?

现在的想法是使用 select as 的方法,比如

Exam.order(score: :desc)
  .select('exams.*', (select count(*) from exams where score > ?) as rank')
  .page(page).per(per_page).map{|e| [e.user_id, e.score]}

问题是,应该 count 出 limit offset 之内的所有用户排名,我不知道?处该填什么,或者这种做法对不对也是值得思考的

最终的目的是,相同分数用户排名并列,比如排行需要 [1, 1, 2, 2, 2, 6, 7, 7, 9] 这样的数据

表结构都不列出来,让别人猜谜吗?

nouse 回复

我一开头就说了的,我觉得可能是你没理解我的意思

现在有一张 exam_result 表,表里有 user_id,score 字段

如果先排名后分页,你需要 window function:

select
  user_id,
  score,
  dense_rank() over (order by score desc) as rank
from exam_result
order by score desc, id asc
limit 4
offset 2;

如果先分页后排名,把上述查询改成子查询就行:

select *, dense_rank() over (order by score desc) as rank
from (
  -- select, limit, offset
) t

或者用分页完成后在 Ruby 层面算。

https://www.postgresql.org/docs/current/static/tutorial-window.html https://www.postgresql.org/docs/current/static/functions-window.html

darkbaby123 回复

我需要的是先排名后分页,你的答案很具体,非常感谢~😁

tinyfeng 关闭了讨论。 02月12日 14:03
需要 登录 后方可回复, 如果你还没有账号请 注册新账号