![](/img/trans.png)
[英]Not sure how to write a query to return column associated with max value in group by
[英]Rails query for associated model with max column value
我有3种模型:Author,Book和Page。 页面属于书籍,书籍属于作者,因此:
class Author < ActiveRecord::Base
has_many :books
end
class Book < ActiveRecord::Base
belongs_to :author
has_many :pages
end
class Page < ActiveRecord::Base
belongs_to :book
end
Page模型有一个称为page_number的列。 我正在使用Postgres。
我的问题是:假设有一个作者@author
,如何查询该作者的所有最后一页? 换句话说,我想要那个作者写的每本书的最后一页。 我正在尝试以下不起作用的方法:
Page.where(book_id: @author.books.pluck(:id)).select('MAX(page_number), *').group(:book_id)
编辑
以下两行有效,但我很想学习更快/更清洁的解决方案:
all_pages = Page.where(book: @author.books)
last_pages = all_pages.select{ |a| !all_pages.select{ |b| b.book_id == a.book_id}.any?{ |c| c.page_number > a.page_number } }
最有效的方法可能是利用postgres的窗口功能
这样的查询不适合activerecord的通用用例,因此您可能必须使用find_by_sql
,但这很值得。
在您的情况下,最好先获取图书ID,因为加入或进行其他子查询可能没有优势-您的电话。
假设您有@author.books.ids
中的书籍ID列表。 我们想要的下一件事情是一本书的“分组依据”页面列表,因此我们可以为每个组提取最后一页。 令1,2为有关作者的书号。
我们可以在postgres中使用window函数和rank
函数来创建一个结果集,其中页面在书的分区(组)上排名。 我们甚至将这些分区按页码排序,以便最大页码(最后一页)位于每个分区的顶部。 查询如下所示:
select
*,
rank() over (
partition by book_id order by page_number desc
) as reverse_page_index
from pages
where book_id in (1,2)
我们想象的pages
结果集将如下所示。
author 1, book 1, page 3, rank 1
author 1, book 1, page 2, rank 2
author 1, book 1, page 1, rank 3
author 1, book 2, page 6, rank 1
author 1, book 2, page 5, rank 2
author 1, book 2, page 4, rank 3
author 1, book 2, page 3, rank 4
author 1, book 2, page 2, rank 5
author 1, book 2, page 1, rank 6
页面记录按书分区,按页码升序排序,并在其分区中排名。
如果在执行窗口计算之后 ,如果只希望每本书排名第一(最后一页),则可以使用子选择,如下所示:
select *
from
(
select
*,
rank() over (
partition by book_id order by page_number desc
) as reverse_page_index
from pages
where book_id in (1,2)
) as pages
where reverse_page_index = 1;
我们将上面想象的结果集过滤到仅排名(reverse_page_index)为1(即最后一页)的页面记录中。
现在我们的结果集将是:
author 1, book 1, page 3, rank 1
author 1, book 2, page 6, rank 1
您还可以按最后修改日期或您需要的顺序订购此结果集。
在find_by_sql
该查询,您将有一些activerecord对象要使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.