在一个 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]
我想运行以下查询:
/* 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]