繁体   English   中英

Rails查询关联模型的最大列值

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM