如何表达 multi-table join in Rails

How to express multi-table join in Rails

我的查询看起来(有点)像这样:

SELECT
  t.strategy_id, SUM(t.price*t.qty), p.currency
FROM   
  trades t, products p
WHERE
  t.symbol = p.symbol and
  (DATE(trade_time) > '2015-01-01' and DATE(trade_time) < DATE(NOW()))
GROUP 
  BY t.strategy_id, SYMBOL, DATE(trade_time) WITH ROLLUP

我如何在 "Rails-y" 中最好地表达这一点?由于结果是来自两个 table 的字段的复合,我应该创建一个模型 StrategyPnl 吗?它应该派生自 ActiveRecord::Base 吗?可能不是,因为它没有 table,或者...?

顺便说一句,我在这些 table 之间没有关联,这是一项要求吗?

我想写这样的东西:

stratpnl.select().where().group()....

并获取这个新 class/model 的数组,但我不知道该怎么做?

*************************** 编辑 ******************* ********

我只是在回答这个问题,因为实际的 table 在这个问题中并不重要:

假设两个 tables A 和 B 没有任何关系(FK 或其他)

SELECT A.FIELD_Y, B.FIELD_X
FROM A,B
WHERE A.INTEGER_X > B.INTEGER_Y
GROUP BY A.NAME

有什么方法可以用漂亮的模型在 Rails 中表达这个查询吗?我知道我可以做到:

@result = ActiveRecord::Base.connection.execute(sql)

但这只会给我一个二维字段数组,我更愿意使用 ActiveRecords 功能并引用对象和字段,因为它在那里。

在不知道正确的模型关系的情况下,您可以使用 ActiveRecord 执行以下操作:

strategies_data = \
  Trade. # assuming at least one table has an associated model
  joins("INNER JOIN products ON products.symbol = trades.symbol").
  where("DATE(trade_time) BETWEEN ? AND ?", Date.new(2015, 1, 1), Date.today).
  group("trades.strategy_id, trades.symbol, DATE(trade_time) WITH ROLLUP").
  select("trades.strategy_id AS id,
          SUM(trades.price*trades.qty) AS strategy_price,
          products.currency AS currency")

然后:

sd = strategies_data.first
sd.id #=> gives you strategy_id
sd.strategy_price #=> gives you total price
sd.currency #=> gives you the currency

稍微调试一下,应该可以。

更新:

如果您还希望事情在语义上也是正确的(就 类 而言),如果您不介意放慢速度,请添加此步骤:

strategy_columns = %i{id strategy_price currency}
strategy_struct = Struct.new(*strategy_columns)
strategies = \
  strategies_data.map do |sd|
    attributes = \
      strategy_columns.each_with_object({}) do |attr, hash|
        hash[attr] = sd.public_send(attr)
      end

    strategy_struct.new(attributes)
  end