以下のクエリを 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")
クエリはすべて DB で動作する必要があり、何百万ものレコードを並べ替えてスライスする必要があるため、ハイブリッド Ruby ソリューションであってはなりません。
私は問題を設定して、通常のuser
テーブルに対して実行するようにし、その代わりに別のテーブルでプレイできるようにしました。
回答可否の制限
User
クエリは、すべての通常の属性を持つオブジェクトを返す必要がありますextra_metric_we_care_about
各ユーザー オブジェクトには、age_in_seconds
およびも含める必要があります。compound_computed_metric
- クエリは、複数の場所で文字列を出力するだけでロジックを複製するべきではありません-同じことを2回行うことを避けたいです
- [更新] 数百万のレコードで構成される可能性のある結果セットを DB で並べ替えてスライスしてから Rails に戻すことができるように、クエリはすべて DB で実行できる必要があります。
- [更新] ソリューションは 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
既存のクラスを使用してコンソールで再生できるように、問題を多少工夫したことに注意してください。
編集
- 私が使用しているDBはPostgresです。
- クエリがすべて DB で実行されることを 100% 明確にしたかどうかはわかりません。ロジックの一部が基本的にRailsで行われている場合、ハイブリッドな答えになることはできません。計算列を使用して何百万ものレコードを並べ替えてスライスできるようにしたいので、これは重要です。