ruby-on-rails - 通过 Rails 和 Postgresql 中对象的属性总和限制查询
问题描述
我有一个 Lead 模型,它有一个名为“sms_price”的预先计算的浮点列。我希望允许用户向这些潜在客户发送短信,并为他们的活动分配预算(类似于您在 fb 广告上可以找到的内容)。
我需要一个可以通过这些潜在客户的总价格限制潜在客户数量的范围。例如,如果用户定义了 200 的总预算
- 编号:1 | 短信价格:0.5 | 总价格:0.5
- 编号:2 | 短信价格:1.2 | 总价格:1.7
- 编号:3 | 短信价格:0.9 | 总价格:2.6
- ...
- 编号:94 | 短信价格:0.8 | total_price: 199.4 <--- 在这里停止查询
- 编号:95 | 短信价格:0.7 | 总价:200.1
所以我需要在我的范围内做两件事:
- 递归计算总价
- 仅获取总价低于所需预算的潜在客户
到目前为止,我只设法使用此范围完成了第一项任务(递归计算总价):
scope :limit_by_total_price, ->{select('"leads".*, sum(sms_price) OVER(ORDER BY id) AS total_price')}
这有效,如果我这样做,Lead.limit_by_total_price.last.total_price
我会得到38039.7499999615
现在我需要的是一种仅检索总价低于预算的潜在客户的方法:
scope :limit_by_total_price, ->(budget){select('"leads".*, sum(sms_price) OVER(ORDER BY id) AS total_price').where('total_price < ?', budget)}
但它不识别 total_price 属性:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "total_price" does not exist
为什么它识别单个对象中的 total_price 属性而不是范围?
解决方案
问题是在 SELECT 子句中计算的列不可用于同一语句中的 WHERE 子句。为了做你想做的事,你需要一个子查询。
from
您可以使用 ActiveRecord 的方法执行此操作,但仍留在 Rails 世界中。此 Hashrocket 博客文章很好地说明了该技术。
在您的情况下,它可能看起来像这样(由于复杂性,我将使用类方法而不是范围):
def self.limit_by_total_price(budget)
subquery = select('leads.*, sum(leads.sms_price) over(order by leads.id) as total_price')
from(subquery, :leads).where('total_price < ?', budget)
end
推荐阅读
- java - 为什么我不能将导航抽屉切换到右侧?
- vue.js - 具有 vuetify 依赖项的 Vue 库
- c# - 确定使用 Zzz 实体框架扩展和 BulkInsert 时插入的记录数
- html - 选中一个或多个复选框并提交后,复选框的一部分消失
- html - 超链接到 about:blank
- typescript - 带有异步和等待的打字稿:在分配之前使用变量.ts(2454)
- python - 使用 tf.keras.utils.Sequence 和 model.fit_generator 和 use_multiprocessing=True 生成警告
- python-3.x - xmlrpc 抛出 http.client.badstatusline 后如何查看响应
- c++ - 重载输入运算符。简单分数类
- powershell - 将数据提取到 CSV 但只需要前 4 个字符 - Powershell