Rails:查询子项和孙项,对子项运行方法,对孙项运行SQL SUM--导致数组?



>Models:

class Category < ApplicationRecord
has_many :inventories
has_many :stocks, through: :inventories
end
class Inventory < ApplicationRecord
belongs_to :category
has_many :stocks
end
class Stock < ApplicationRecord
belongs_to :inventory
end

目标:

实现高效的 ActiveRecord 查询,该查询可构建如下所示的数组:

[
{ name: "Supplies", count: 10.00, total_value: 40.00 },
{ name: "Materials", count: 25.00, total_value: 30.00 }
]

name-> 只是库存模型中的常规属性

count->股票表中 :count列上的 SQL SUM

total_value-> 来自库存模型中执行一些数学运算的方法

这可能是一个完全的幻想,但我有一个很大的数据集,所以我试图让它变得超高效。有什么想法吗?


编辑以回答问题:

total_value 是库存上的一个方法,然后调用库存上方法的总和:

def total_value
stocks.map do |stock|
stock.total_cost
end.sum
end

total_cost是库存上的一种方法:

def total_cost
cost_per_unit * count
end

你来了:query = Inventory.group(:id, :name).select(:id, :name).left_joins(:stocks).select("SUM(stocks.count) AS count").select("SUM(stocks.cost_per_unit * stocks.count) AS total_value")

query.as_json提供了您正在寻找的东西。

您也可以通过find_each访问数据:query.find_each { |record| puts "record #{record.name} has a total value of #{record.total_value}" }

如果要避免在SQL中重复total_value逻辑,则必须加载股票记录,如果有很多,这会大大减慢计算速度:

升级模型

class Inventory < ApplicationRecord
def stocks_count
stocks.sum(&:count)
end
def total_value
stocks.sum(&:total_cost)
end
end

和查询

Inventory.preload(:stocks).map do |inventory|
{
name: inventory.name, 
count: inventory.stocks_count, 
total_value: inventory.total_value
}
end

如果要最大程度地优化查询,可以考虑在inventories表上缓存 2 列total_valuestocks_count列。每次其中一个股票更改(创建、删除、更新(时,您都会更新它们。它更难维护,但这是最快的选择。

最新更新