Gem 使用 Kaminari 分页时,遇到使用 distinct 的语句,分页会不准确

wfwdex · 发布于 2017年05月31日 · 最后由 zj0713001 回复于 2017年06月08日 · 587 次阅读
19842

使用kaminari对去重的语句进行分页时,生成的分页语句有问题:

logs = OperationLog.select(:user_id).where(interface_id: params[:interface_id]).page(param_page).per(param_limit).distinct.includes(:user)

生成的语句

-- 分页语句
SELECT  DISTINCT `operation_logs`.`user_id` FROM `operation_logs` WHERE `operation_logs`.`interface_id` = 1 LIMIT 25 OFFSET 0
-- 查询关联用户
SELECT `users`.* FROM `users` WHERE `users`.`id` IN (150, 123, 175, 126, 133, 124)
-- 获取总记录数
SELECT DISTINCT COUNT(DISTINCT `operation_logs`.`id`) FROM `operation_logs` WHERE `operation_logs`.`interface_id` = 1

事实上总记录数并没有按DISTINCT指定的字段去重,导致总记录数是未去重的数量,

查了kaminari项目README.md和google,都没找到解决方法,目前使用的是Kaminari.paginate_array,对总结果分页,这样显然是不对的,记录数多了之后,性能有很大问题。

请问这个问题怎么解决?

共收到 10 条回复
1342

distinct 放在 page 前面调用的话呢?

19842
1342ywjno 回复

谢谢回复,试了一下,生成的语句是一样的,没有变化。

19842

换了个思路,使用以下方式解决....

logs = OperationLog.select(:user_id).where(interface_id: params[:interface_id]).page(param_page).per(param_limit).group(:user_id).includes(:user)
3753

你这样会丢OperationLog的,每个user未必只有一个log,group是聚合~ 所以你的需求是什么~

13582
OperationLog.joins(:user).select(:user_id).distinct.where(interface_id: params[:interface_id]).page(1).per(10) 

这样试试呢?

19842
3753zj0713001 回复

我的需求是让记录按我要求的字段去重后可以正常分页。 现在看来不能用distinct,还是用group比较好。

19842
13582rd084c 回复

谢谢回复,我的项目里 users和logs是在不同的数据库里,所以不能用join

3753
19842wfwdex 回复

我的问题是~ group并不是去重,会丢数据的~ 比方说log有 create_at 聚合以后只能显示一组相同字段数据里的某一个值了

19842
3753zj0713001 回复

谢谢回复,没关系,我的需求里在分组时,只需要算分组后每组数据有多少条,或者某个数值字段的总合,所以分组正合适的。

是我之前把概念搞错了,所以错用了distinct。

3753
19842wfwdex 回复

那这个需求就恰好是group的使用场景~

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册