【问题标题】:How do you group by years from 'created_at', using ActiveRecord?您如何使用 ActiveRecord 从“created_at”按年份分组?
【发布时间】:2018-07-27 08:49:50
【问题描述】:

在 SQL 中,我会使用这样的东西:

SELECT year(created_at)
FROM videos
GROUP BY year(created_at)

如何使用 Rails 运行此查询?

我试过这个:

Video.all.group_by { |m| m.created_at.year }

...但这将返回按相应年份分组的所有记录,这还不错,除了返回数百条记录,而我只需要知道年份。

任何指针?

如果您想知道我使用的是 Rails 5.1.5 和 MariaDB (10.2.14-MariaDB-10.2.14+maria~xenial-log)。

【问题讨论】:

  • 你的意思是你只想要几年? Event.all.group_by { |m| m.created_at.year }.keys
  • 好吧,我现在感觉很笨。这样可行。该查询会和我发布的 SQL 一样高效吗?
  • @user3209270:很遗憾,不,这是最慢和最浪费的方法之一。

标签: ruby-on-rails ruby-on-rails-5 mysql2


【解决方案1】:

你可以做这样的事情来获得一系列独特的年份......

Video.pluck(:created_at).map{ |dt| dt.year }.uniq

【讨论】:

    【解决方案2】:

    事实证明,pluck 接受表达式,而不仅仅是列名。因此,您可以这样做以获得最大效率(以便携性为代价)。

    Video.distinct.pluck("year(created_at)") # mysql
    Video.distinct.pluck("extract(year from created_at)") # postgresql
    

    与运行原始 sql 的效率相同(来自我的另一个答案),但看起来更像 ActiveRecord-y。

    如果您想要一个便携的解决方案,那么我想不出比Mark's answer 更好的东西了。

    【讨论】:

      【解决方案3】:

      并非所有内容都可以用 activerecord-speak 来表达而不会在这里或那里失去效率。或者有些东西根本无法表达。这就是你可以运行任意 SQL 的原因:

      Video.connection.execute("select year(created_at)....")
      

      在实际阅读过您的 SQL 之后,您想要不同年份的记录吗?那么,也许是这个?应该更快(需要基准测试)。

      SELECT DISTINCT YEAR(created_at)  FROM videos
      

      【讨论】:

      • 当然,但是我的偏执促使我在 ActiveRecord 中找到解决方案,以防 DBMS 由于某种原因无法处理 SQL。
      【解决方案4】:

      你也可以这样做:

      Video.all.map {|u| u.created_at.year}
      

      这将返回一个数组,其中包含每个 Video 的创建年份。

      【讨论】:

      • 这将完整加载所有视频。
      【解决方案5】:

      我正在使用

      Event.group("strftime('%Y', created_at)")
      

      例如:

      Event.group("strftime('%Y', created_at)").count
      

      有输出:

      {"2019"=>456}
      

      您甚至可以这样按孩子的created_at 分组:

      Application.group("strftime('%Y', events.created_at)")
      

      这要求applications 在我的特定情况下有许多events。

      【讨论】:

        【解决方案6】:

        如果你只想要几年的数据,你可以这样做

        videos = Video.group("created_at").select("videos.created_at")
        

        它只会获取created_at 列

        您可以通过 created_at 列访问年份

        videos.first.created_at.year
        

        【讨论】:

        • 比加载完整的视频要好,但是这段代码仍然会实例化一些视频模型,这完全是浪费 cpu 周期。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多