【发布时间】:2013-08-01 12:38:42
【问题描述】:
我想使用 Squeel 重构下面的查询。我想这样做,以便我可以将其中的运算符链接起来,并在查询的不同部分重新使用逻辑。
User.find_by_sql("SELECT
users.*,
users.computed_metric,
users.age_in_seconds,
( users.computed_metric / age_in_seconds) as compound_computed_metric
from
(
select
users.*,
(users.id *2 ) as computed_metric,
(extract(epoch from now()) - extract(epoch from users.created_at) ) as age_in_seconds
from users
) as users")
查询必须全部在数据库中运行,并且不应该是混合 Ruby 解决方案,因为它必须对数百万条记录进行排序和切片。
我已经设置了问题,以便它应该针对普通的user 表运行,这样您就可以使用它的替代方案。
可接受答案的限制
- 查询应返回具有所有正常属性的
User对象 - 每个用户对象还应该包括
extra_metric_we_care_about、age_in_seconds和compound_computed_metric - 查询不应该通过在多个地方打印出一个字符串来重复任何逻辑 - 我想避免两次做同样的事情
- [更新] 查询应该可以在数据库中执行,以便在返回 Rails 之前可以在数据库中对可能包含数百万条记录的结果集进行排序和切片
- [更新] 该解决方案应该适用于 Postgres 数据库
我想要的解决方案类型示例
下面的解决方案不起作用,但它显示了我希望达到的优雅类型
class User < ActiveRecord::Base
# this doesn't work - it just illustrates what I want to achieve
def self.w_all_additional_metrics
select{ ['*',
computed_metric,
age_in_seconds,
(computed_metric / age_in_seconds).as(compound_computed_metric)]
}.from{ User.w.compound_computed_metric.w_age_in_seconds }
end
def self.w_computed_metric
where{ '(id *2 ) as computed_metric' }
end
def self.w_age_in_seconds
where{ '(extract(epoch from now()) - extract(epoch from created_at) ) as age_in_seconds' }
end
end
您应该能够在现有数据库上运行它
请注意,我有些人为地设计了这个问题,以便您可以使用现有的 User 类并在控制台中使用它。
编辑
- 我使用的数据库是 Postgres。
- 我不确定我是否 100% 清楚地表明查询应全部在数据库中执行。如果某些逻辑本质上是在 Rails 中完成的,那么这不能是一个混合的答案。这很重要,因为我希望能够使用计算列对数百万条记录进行排序和切片。
【问题讨论】:
-
只是用我的方式扔垒球......解决这个问题有多难......呃!争夺赏金的竞赛正在进行中!
-
我不明白。您所描述的可以简单地解决,无需任何花哨的 squeel 链接。无需使用子查询。 Compound_computed_metric 是针对表中的每一行计算的,没有聚合。
-
@wanghq - 如果是这样的话,那就太好了。你能写出实现这一目标的查询吗?错误 - 我会看看,你
-
@erroric - 避免重复的 SQL(和 DB 工作)很难。我认为它不适合您发布的其他两个示例,尽管您显然与我的思路相同
标签: ruby-on-rails activerecord arel squeel