将使用命名范围对错误计数的奇怪情况进行分页

发布于 2024-08-05 18:15:37 字数 1483 浏览 9 评论 0原文

我最近将查询分成 4 个命名范围,以便更容易重新排序和分页,否则一直工作正常,但现在在计算页数时出现问题。

  named_scope :loc, lambda { |id| { :conditions => ['location_id = ?', id ] } }
  named_scope :datem, lambda { |*args| { :joins => :scannables, :conditions => [ "scannables.bookdate BETWEEN ? and ?", (args[0].to_date || 3.days.from_now), (args[0].to_date+(args[1] || 3)) ], :group => 'scannables.hostel_id', :having => 'SUM(scannables.available) > ' + ((args[1] || 3).to_i-1).to_s } }
  named_scope :order_by_external_desc, :include => :external_ratings, :order => 'SUM(scannables.available) DESC, external_ratings.rating DESC'
  named_scope :order_by_external_asc, :include => :external_ratings, :order => 'SUM(scannables.available) DESC, external_ratings.rating ASC'

像这样使用,并在末尾抛出分页...

@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc.paginate(:per_page => 15, :page => params[:page])

例如,分页将显示有 6 页,每页 15 页,但是当您到达第 4 页时,第 5-6 页消失...并且如果您尝试跳到第 5 页或第 6 页直接说它们不存在。

看着它,我意识到分页的问题是,

c=@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc.size

c = 78

然而,

c=@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc

c.size = 56

为前者生成的sql比后者短约8行,并且忽略了我的sql HAVING子句,这导致它返回更多结果......

任何想法如何解决这个问题?

I recently broke up my query into 4 named scopes to make it easier to re-sort and will paginate which otherwise always worked fine now has problems calculating the number of pages.

  named_scope :loc, lambda { |id| { :conditions => ['location_id = ?', id ] } }
  named_scope :datem, lambda { |*args| { :joins => :scannables, :conditions => [ "scannables.bookdate BETWEEN ? and ?", (args[0].to_date || 3.days.from_now), (args[0].to_date+(args[1] || 3)) ], :group => 'scannables.hostel_id', :having => 'SUM(scannables.available) > ' + ((args[1] || 3).to_i-1).to_s } }
  named_scope :order_by_external_desc, :include => :external_ratings, :order => 'SUM(scannables.available) DESC, external_ratings.rating DESC'
  named_scope :order_by_external_asc, :include => :external_ratings, :order => 'SUM(scannables.available) DESC, external_ratings.rating ASC'

Used like so with paginate thrown on the end...

@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc.paginate(:per_page => 15, :page => params[:page])

Paginate will for example show that there are 6 pages of 15 each but when you get to page 4, pages 5-6 disappear... and if you try jumping to 5 or 6 directly they don't exist.

Looking at it, I realized to problem will paginate is having is that

c=@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc.size

c = 78

however

c=@location = Place.loc(params[:id]).datem(user_cart.getDate,user_cart.getDays).order_by_external_desc

c.size = 56

The sql getting generated for the former is about 8 lines shorter than that of the latter and neglects my sql HAVING clause which causes it to return more results...

Any ideas on how to fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

む无字情书 2024-08-12 18:15:37

当使用 group_by/having 时 - 正如您在日期命名范围中所做的那样 - 不幸的是,ActiveRecord 的计数错误。我认为你对此无能为力。我也不确定这是否一定是 ActiveRecord 中的错误 - 或者只是在使用 ActiveRecord 时由于生成的 SQL 的性质而实际上无法正确计算的问题。

无论哪种方式,您都需要解决这个“错误”。

执行此操作的方法是在单独的 SQL 语句(给出正确结果的语句)中处理计数,并将其添加到分页结果中,如下所示:

total_entries = Place.count(sql) # or the combinations of named_scopes etc with a .size or whichever one gives you the correct count

Place.scopes.paginate(:per_page => 15, :page => params[:page], :total_entries => total_entries) # where scopes are all of your named scopes as you have in your examples

When using a group_by/having - as you do in your datem named_scope - ActiveRecord gets the count wrong unfortunately. I don't think there is much you can do about that. I am also not certain whether this is necessarily a bug in ActiveRecord - or just a thing that can't actually be calculated correctly when using ActiveRecord by the nature of the SQL generated.

Either way - you will need to work around this 'bug'.

The way to do this is to tackle the count in a separate SQL statement (the one that gives you the correct results), and adding it to the paginate results like so:

total_entries = Place.count(sql) # or the combinations of named_scopes etc with a .size or whichever one gives you the correct count

Place.scopes.paginate(:per_page => 15, :page => params[:page], :total_entries => total_entries) # where scopes are all of your named scopes as you have in your examples
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文