在一个 SQL 查询中基于 ActiveRecord 范围为集合选择 MIN 和 MAX

Selecting MIN and MAX for a collection, based on an ActiveRecord scope, in one SQL query

我想运行以下查询:

/* Inside a heredoc */
SELECT
  MIN("books"."page_count") AS min,
  MAX("books"."page_count") AS max
FROM "books"
  WHERE "books"."author_id" IN (#{authors.pluck(:id).map { |id| "'#{id}'" }.join(",")})
  AND "books"."publisher_id" IN (#{publishers.pluck(:id).map { |id| "'#{id}'" }.join(",")});

但我不想在末尾手动编写 WHERE 子句,使用那种丑陋的插值,我想使用我在 Book 上定义的范围,例如:

query = Book.by_author(authors).by_publisher(publishers).select('MIN("books"."page_count") as min, MAX("books"."page_count") as max').first
attrs = [query["min"], query["max"]]

我知道这行不通,因为 Book.my_scope... 需要 return 一组书籍,而我正在寻找数值。

我知道我可以做,例如:

query = Book.by_author(authors).by_publisher(publishers)
attrs = [query.minimum(:page_count), query.maximum(:page_count)]

但这会导致两个 SQL 查询,这似乎完全没有必要。

有没有一种 Rails-y 方法可以做到这一点,同时保持可链接范围的灵活性,无需 heredoc 插值,并且在一个 SQL 查询中?

您可以将其定义为 class method:

class Book
  class << self
    def minmax_page_count
      count = select('MIN(page_count) OVER (), MAX(page_count) OVER ()').take
       
      [count.min, count.max]
    end  
  end
end

Book.by_author(authors).by_publisher(publishers).minmax_page_count # => [1, 2]