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

Rails中基于季度值查询:获取季度支出下滑的用户

筛选当前季度支出少于上一季度的用户

核心思路

先算出当前季度和上一季度的时间范围,再按用户分组统计两个季度的支出总和,最后筛选出「当前季度总和 < 上一季度总和」的用户。结合你已有的users.requested_users集合,直接基于这个集合做关联查询即可,避免N+1性能问题。

步骤1:定义季度时间范围

用Rails自带的日期方法快速获取两个季度的起止日期:

# 当前季度起止日期
current_quarter_start = Date.today.beginning_of_quarter
current_quarter_end = Date.today.end_of_quarter

# 上一季度起止日期
last_quarter_start = Date.today.last_quarter.beginning_of_quarter
last_quarter_end = Date.today.last_quarter.end_of_quarter

步骤2:基于现有集合筛选用户

通过left_joins关联支出表,用CASE语句分别统计两个季度的支出总和,最后用having子句筛选符合条件的用户:

users = users.requested_users
            .left_joins(:expenditures)
            .select(
              "users.*",
              # 统计上一季度总支出
              "SUM(CASE WHEN expenditures.entry_date BETWEEN ? AND ? THEN expenditures.amount ELSE 0 END) AS last_quarter_total",
              # 统计当前季度总支出
              "SUM(CASE WHEN expenditures.entry_date BETWEEN ? AND ? THEN expenditures.amount ELSE 0 END) AS current_quarter_total"
            )
            .group("users.id")
            # 筛选当前季度支出更少的用户
            .having("current_quarter_total < last_quarter_total")
            # 绑定参数避免SQL注入
            .bind(last_quarter_start, last_quarter_end, current_quarter_start, current_quarter_end)

可选:封装成模型Scope复用

如果需要多次使用这个筛选逻辑,可封装成User模型的Scope,简化调用:
在user.rb中添加:

scope :spent_less_current_quarter_than_last, -> {
  current_quarter_start = Date.today.beginning_of_quarter
  current_quarter_end = Date.today.end_of_quarter
  last_quarter_start = Date.today.last_quarter.beginning_of_quarter
  last_quarter_end = Date.today.last_quarter.end_of_quarter

  left_joins(:expenditures)
    .select(
      "users.*",
      "SUM(CASE WHEN expenditures.entry_date BETWEEN ? AND ? THEN expenditures.amount ELSE 0 END) AS last_quarter_total",
      "SUM(CASE WHEN expenditures.entry_date BETWEEN ? AND ? THEN expenditures.amount ELSE 0 END) AS current_quarter_total"
    )
    .group("users.id")
    .having("current_quarter_total < last_quarter_total")
    .bind(last_quarter_start, last_quarter_end, current_quarter_start, current_quarter_end)
}

之后调用就非常简洁:

users = User.all.requested_users.spent_less_current_quarter_than_last

补充说明

  • 用left_joins而非joins:确保没有任何支出记录的用户也会被纳入统计(但这类用户两个季度总和都是0,不会被筛选出来)
  • 参数绑定:严格遵循Rails安全规范,避免SQL注入风险
  • 无支出场景处理:某一季度没有支出时,总和按0计算,比如上一季度有支出、当前季度无支出的用户会被正常筛选出来

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:32:34