【问题标题】:Calculate average age of items in ruby on rails计算 ruby​​ on rails 中物品的平均年龄
【发布时间】:2018-10-24 16:52:42
【问题描述】:

我想找到 Ticket.opened 的平均年龄。 Opened 是我的票证模型上的一个范围。 这将为一张票返回一个不错的结果。

time_ago_in_words(Ticket.last.created_at.to_time)

我想要的是做这样的事情

age = []    
Ticket.opened.each do |t|
    age = time_ago_in_words(t.created_at.to_time)+[]
end
average_age = age/Ticket.opened.count

我知道这段代码很糟糕,但这是我解释我在寻找什么的最佳尝试。

【问题讨论】:

    标签: sql ruby-on-rails activerecord


    【解决方案1】:

    如果您使用 PostgreSQL,那么您可以在单个 SQL 查询中获取平均 created_at 时间:

    avg_created_at = Ticket.opened.average('extract(epoch from tickets.created_at)')
    time_ago_in_words(Time.at(avg_created_at))
    

    EXTRACT(EPOCH FROM ...) 函数返回 created_at 值作为自 1970-01-01 00:00:00 UTC 以来的秒数。这可以在聚合函数中使用,例如average

    我确信 MySQL 也允许这样的查询。

    【讨论】:

    • 不错,真的很优雅!我认为它在 MySQL 上是 avg_created_at = Ticket.opened.average('UNIX_TIMESTAMP(tickets.created_at)')dev.mysql.com/doc/refman/5.5/en/…`
    • 不错的答案!当有更好的解决方案时,不得不说脱帽致敬。 +1
    • 我喜欢这种方法!这是我在控制器中使用的代码: avg_created_at = Ticket.opened.average('UNIX_TIMESTAMP(tickets.created_at)') 视图中的代码: I收到此错误:无法将 FalseClass 转换为确切的数字
    • @timothywright 在您的应用程序中,您使用 MySQL,对吗?你能打开rails控制台并检查avg_created_at = Ticket.opened.average('UNIX_TIMESTAMP(tickets.created_at)')的结果吗?
    • 是的-我使用 mysql。 avg_created_at = Ticket.opened.average('UNIX_TIMESTAMP(tickets.created_at)') (3.7ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO') , @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 (0.8ms) SELECT AVG(UNIX_TIMESTAMP(tickets.created_at)) FROM tickets WHERE tickets.status = 0 => 0.153810397325866跨度>
    【解决方案2】:

    我相信您可以通过将时间转换为整数并计算平均值来得到它。粗略地说:

    times = [2.days.ago, 3.days.ago, 4.days.ago]
    average_ticket_time = Time.at(times.map(&:to_i).sum / times.count) # convert to ints and get average
    time_ago = Time.now - average_ticket_time # time ago from now
    readable_time_ago = (time_ago / 60 / 60).round # divide by 60 secs then 60 mins; round to get closest hour
    # => 72 (hours ago)
    

    或者在一行中:

    ((Time.now - (Time.at(times.map(&:to_i).sum / times.count))) / 60 / 60).round
    

    因此,平均而言,72 小时前。

    您还可以除以额外的 24 来获得以天为单位的时间:在本例中为 3 天,这就是您在这个简单示例中所期望的。

    在您的示例中,您的 times 数组将如下所示:

    times = Ticket.opened.map { |ticket| ticket.created_at.to_i }
    # or perhaps the following, check the performace:
    times = Ticket.opened.pluck(:created_at).map(&:to_i)
    

    希望对您有所帮助 - 让我知道您的进展情况。

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 2023-03-28
      • 1970-01-01
      • 2014-10-17
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-10-31
      相关资源
      最近更新 更多