如何表达 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
我的查询看起来(有点)像这样:
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