gpt4 book ai didi

ruby-on-rails - 您将如何使用Squeel进行Rails子查询?

转载 作者:行者123 更新时间:2023-12-04 03:52:16 24 4
gpt4 key购买 nike

我想使用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_aboutage_in_secondscompound_computed_metric
  • 查询不应仅通过在多个位置打印一个字符串来重复任何逻辑-我想避免两次做相同的事情
  • [更新]查询应该在数据库中都是可行的,以便在返回Rails之前可以在数据库中对可能包含数百万条记录的结果集进行排序和切片。
  • [更新]该解决方案应该适用于Postgres DB

  • 我想要的解决方案类型示例

    下面的解决方案不起作用,但是它显示了我希望实现的优雅类型
    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中完成的,那不可能是一个混合答案。这很重要,因为我希望能够使用计算所得的列对数百万条记录进行排序和切片。
  • 最佳答案

    我有两种解决方案。我的数据库是mysql,我简化了演示代码,我想您可以扩展它。

    第一种是Squeel方式,我在Squeel中混合了“sift”和在ActiveRecord Query中混合了“from”。
    我现在安装了postgresql并测试了我的解决方案,似乎很难同时使用“squeel”和“epoch from”,但是我在postgresql中找到了另一种方式,称为“date_part”。我还修改了sql并减少了计算重复项:

    class User < ActiveRecord::Base           
    sifter :w_computed_metric do
    (id * 2).as(computed_metric)
    end

    sifter :w_age_in_seconds do
    (date_part('epoch' , now.func) - date_part('epoch', created_at)).as(age_in_seconds)
    end

    sifter :w_compound_computed_metric do
    (computed_metric / age_in_seconds).as(compound_computed_metric)
    end

    def self.subquery
    select{['*', sift(w_computed_metric) , sift(w_age_in_seconds)]}
    end

    def self.w_all_additional_metrics
    select{['*', sift(w_compound_computed_metric)]}.from("(#{subquery.to_sql}) users")
    end
    end

    它产生了sql:
    SELECT *, "users"."computed_metric" / "users"."age_in_seconds" AS compound_computed_metric 
    FROM (SELECT *,
    "users"."id" * 2 AS computed_metric,
    date_part('epoch', now()) - date_part('epoch', "users"."created_at") AS age_in_seconds FROM "users"
    ) users

    您可以使用控制台进行测试:
    > User.w_all_additional_metrics.first.computed_metric
    => "2"
    > User.w_all_additional_metrics.first.age_in_seconds
    => "633.136693954468"
    > User.w_all_additional_metrics.first.compound_computed_metric
    => "0.00315887551471441"

    第二种是ActiveRecord方式,因为您的sql并不是很复杂,所以您可以在ActiveRecord Query中将其链接起来,在某些范围内就足够了:
    class User < ActiveRecord::Base
    scope :w_computed_metric, proc { select('id*2 as computed_metric') }
    scope :w_age_in_seconds, proc { select('extract (epoch from (now()-created_at)) as age_in_seconds') }
    scope :w_compound_computed_metric, proc { select('computed_metric/age_in_seconds as compound_computed_metric') }

    def self.subquery
    select('*').w_computed_metric.w_age_in_seconds
    end

    def self.w_all_additional_metrics
    subquery.w_compound_computed_metric.from("(#{subquery.to_sql}) users")
    end
    end

    这将产生以下SQL:
    SELECT 
    *, id*2 as computed_metric,
    extract (epoch from (now()-created_at)) as age_in_seconds,
    computed_metric / age_in_seconds as compound_computed_metric
    FROM (
    SELECT
    *,
    id*2 as computed_metric,
    extract (epoch from (now()-created_at)) as age_in_seconds
    FROM
    "users"
    ) users
    ORDER BY compound_computed_metric DESC
    LIMIT 1

    希望它满足您的要求:)

    关于ruby-on-rails - 您将如何使用Squeel进行Rails子查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17994309/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com