You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails基于group_by实现按年/月/任务类型的关联记录层级计数

三级嵌套时间维度统计的实现方案

核心问题根因

现有代码仅完成按年的一级分组,未实现年-月-任务类型的分层聚合、各层级计数统计,也未做空年份占位、固定月份/任务排序逻辑,输出结构与预期不符。

Controller 层改造

替换原有分组逻辑,实现三层嵌套聚合、预加载关联避免 N+1 查询、空年份占位:

# controller 
@user = User.find(params[:user_id])
scoped_records = @user.records.joins(:task)
                             .includes(:task) # 预加载任务关联,消除N+1查询
                             .where(tasks: { name: ["Buy", "Sell", "Create"] })
                             .order(created_at: :desc)

# 三层嵌套分组结构:年份 -> 月份 -> 任务类型 -> 对应记录数组
@nested_stats = scoped_records.group_by { |rec| rec.created_at.strftime("%Y") }
                             .transform_values do |year_records|
  year_records.group_by { |rec| rec.created_at.strftime("%B") }
              .transform_values do |month_records|
    month_records.group_by { |rec| rec.task.name }
  end
end

# 按需补全连续年份的空值占位(匹配示例中无记录年份显示计数为0的效果,时间范围可自行调整)
(2018..Date.current.year).reverse_each do |year|
  @nested_stats[year.to_s] ||= {}
end

View 层改造

替换原有遍历逻辑,实现层级缩进、自动计数、固定排序、可选的记录创建日期展示:

<!-- view.html.erb -->
<% month_order = Date::MONTHNAMES.compact %>
<% task_order = ["Buy", "Sell", "Create"] %>

<% @nested_stats.each do |year, month_map| %>
  <% year_total = month_map.values.sum { |task_map| task_map.values.sum(&:count) } %>
  <%= "#{year} (#{year_total})" %>

  <% # 按自然时间倒序排列月份,避免字符串排序错乱 %>
  <% sorted_months = month_map.sort_by { |month_name, _| -month_order.index(month_name) } %>
  <% sorted_months.each do |month_name, task_map| %>
    <% month_total = task_map.values.sum(&:count) %>
    <%= "    #{month_name} (#{month_total})" %>

    <% # 按Buy/Sell/Create固定顺序排列任务类型 %>
    <% sorted_tasks = task_map.sort_by { |task_name, _| task_order.index(task_name) } %>
    <% sorted_tasks.each do |task_name, records| %>
      <% task_total = records.count %>
      <%= "        -> #{task_name} (#{task_total})" %>
      <% # 取消下方注释即可展示每条记录的具体创建日期 %>
      <%# records.each do |rec| %>
          <%# "            记录创建于:#{rec.created_at.strftime("%Y-%m-%d")}" %>
      <%# end %>
    <% end %>
  <% end %>
<% end %>

关键优化点

  • 用 Ruby 内置Date::MONTHNAMES固定月份排序,避免字符串比较导致 12 月排在 1 月之前的顺序错乱问题
  • 固定任务类型的展示顺序,与示例输出结构完全匹配
  • 预加载 task 关联,避免每条记录单独查询任务表造成的性能损耗
  • 各层级计数自动累加,无需额外编写聚合 SQL
  • 空年份占位逻辑可按需调整范围,不需要的话直接删除那段补全年份的代码即可

内容的提问来源于stack exchange,提问作者user9769384

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.25 20:06:07