【问题标题】:Selecting MIN and MAX for a collection, based on an ActiveRecord scope, in one SQL query在一个 SQL 查询中,基于 ActiveRecord 范围为集合选择 MIN 和 MAX
【发布时间】:2021-05-28 15:24:14
【问题描述】:

我想运行以下查询:

/* 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... 期望返回书籍集合,而我正在寻找数值。

我知道我可以做到,例如:

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

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

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

【问题讨论】:

    标签: ruby-on-rails postgresql activerecord


    【解决方案1】:

    您可以将其定义为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]
    

    【讨论】:

      猜你喜欢
      • 2015-07-04
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      • 1970-01-01
      • 2019-12-24
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      相关资源
      最近更新 更多