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
相关产品推荐
相关产品推荐

