Rails 5.2+ / PostgreSQL:聚合函数“平均”计算2个datetime列之间的持续时间

时间:2018-12-23 19:37:02

标签: postgresql ruby-on-rails-5 average aggregate-functions duration

更新2018-12-24 09:45

我想出的一个解决方案是添加一个duration_in_seconds列并在那里存储两个时间戳之间的差异,然后使用该值在几秒钟内进行计算。它可以工作,但我仍然对PostgreSQL和average()函数遇到的问题感到好奇。

原始问题

我正在应用程序中建立报告机制,我需要跟踪records在每个stage中花费的时间。

class Stage < ApplicationRecord
  has_many :record_stages
end

# Join table
class RecordStage < ApplicationRecord
  # id:primary_key
  # stage_id:integer
  # record_id:integer
  # left_state_at:datetime
  # created_at/updated_at:datetime

  belongs_to :stage
  belongs_to :record

  # Both timestamp datatypes, difference is returned in seconds
  def duration_in_seconds
    left_stage_at - created_at
  end
end

class Record < ApplicationRecord
  has_many :record_stages
end

我通过record_stage.left_stage_at - record_stage.created_at(您在创建stage时输入了它)来计算每个阶段花费的时间。

这允许record拥有多个stages,而且我可以跟踪record在每个stage中花费了多长时间。

单条记录(符合我的预期)

record_stage = RecordStage.first
duration = record_stage.duration_in_seconds # => 447.966037
ActiveSupport::Duration.build(duration) # => 7 minutes and 27.966037 seconds

多条记录(报告,不是我所期望的)

但是,当我尝试使用Rails 5.2和PostgreSQL在其上执行聚合average函数时,却没有得到我期望的结果:

stage = Stage.first # => ie, "First Stage"
record_stages = stage.record_stages # Just the 1 record from above in my system
average_duration = record_stages.average("left_stage_at - created_at") # => 0.0

问题

如何计算record_stages集合的平均持续时间?

我知道我可能误会了PostgreSQL聚合average的工作方式,但是我不确定我缺少什么。

最终目标是建立一个像这样的表:

|-------|---------|------------------|
| Stage | Records | Average Duration |
|-------|---------|------------------|
| First | 4       | 2 weeks, 4 days  |
|-------|---------|------------------|
| ...   | 7       | 4 weeks, 5 days  |
|-------|---------|------------------|

0 个答案:

没有答案