【问题标题】:Rails scope based on range of time of associated objects基于关联对象时间范围的 Rails 范围
【发布时间】:2021-07-10 22:50:09
【问题描述】:

我正在尝试创建一个查看模型关联记录的 starts_at 日期时间的高性能范围,并获取关联记录在该窗口内的对象。

例如:

class Championship < ApplicationRecord
  has_many :races
end

class Race < ApplicationRecord
  belongs_to :championship
end

每个Race 记录都有一个starts_at 时间戳。我需要查看每个Championship 的比赛,按starts_at 排序这些比赛,获取第一个(按时间顺序)并检查我们是否已经过去,然后获取最后一个并检查我们是否在那个时间之前时间。

class Championship < ApplicationRecord
  scope :active, -> { joins(:races)...? }

但我真的不确定如何在 SQL 中对这些记录进行排序并获取第一条或最后一条记录以进行评估。

更新(澄清)

c = Championship.create()
r1 = c.races.create(starts_at: '2021-05-01')
r2 = c.races.create(starts_at: '2021-06-01')
r3 = c.races.create(starts_at: '2021-07-01')
r4 = c.races.create(starts_at: '2021-08-01')

假设当前时间是:

  • 04/01/21:冠军应该active
  • 05/01/21: 冠军应该是active
  • 05/15/21: 冠军应该是active
  • 08/15/21:冠军应该active

更新(分辨率) 这是我们最终得到的结果:

scope :active, -> { where(id: Race.select(:championship_id).group(:championship_id).having("MIN(races.starts_at) - interval '1 day' < ?", Time.now).having("MAX(races.starts_at) + interval '2 days' > ?", Time.now).pluck(:championship_id)) }

【问题讨论】:

    标签: sql ruby-on-rails


    【解决方案1】:

    无需订购您的餐桌!

    class Championship < ApplicationRecord
      def self.active
        condition = Races
          .select(:championship_id)
          .group(:championship_id)
          .having('min(races.starts_at) <= ?', date)
          .having('max(races.starts_at) >= ?', date)
        joins(:races).merge(condition)
      end
    
      (...)
    end
    

    PS:如果您遇到性能问题,可以在此列上添加索引 rails generate migration add_index_to_races_starts_at。它应该生成以下迁移:

    class AddIndexToRacesStartsAt < ActiveRecord::Migration[6.1]
      def change
        add_index :products, :part_number
      end
    end
    

    【讨论】:

    • ? 哇,我想我想得太多了! ?今晚晚些时候我会试试这个来确认。感谢您亲切地敲了敲头。
    • 伦纳德,这实际上是行不通的。让我试着解释一下。假设锦标赛运行 6 个月,每个月有 1 场比赛。如果我们按照您的建议进行范围,那么当比赛开始时间与当前时间匹配时,该锦标赛只会在一个非常小的窗口内被视为“活跃”。我们真正需要的是从头到尾参加锦标赛,看看我们是否在那个窗口内。也许像 Championship.joins(:races).where("MIN(races.starts_at)
    • 对不起,我不明白你想要什么。您能否用一个带日期的具体示例来编辑您的帖子?
    • 当然,抱歉没有很好地解释这一点。我刚刚添加了一个更新,希望能解决一些问题?
    • 你能确认更新后的查询没问题吗?
    猜你喜欢
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    相关资源
    最近更新 更多