[英]How to perform single sql query to sum columns from grouped results in activerecord?
[英]How to efficiently retrieve groups of objects from activerecord with a single SQL query?
我有一個表products
,上面有一個product_type_code
列。 我想做的是根據此列檢索不同數量的對象(例如:3個product_type_code = 'fridge'
產品,6個product_type_code = 'car'
產品,9個product_type_code = 'house'
,等等。 )。
我知道我可以這樣:
fridges = Product.where(product_type_code: 'fridge').limit(3)
houses = Product.where(product_type_code: 'house').limit(9)
[...]
甚至創建這樣的范圍:
# app/models/product.rb
scope :by_product_type_code, -> (material) { where(product_type_code: product_type_code) }
但是,這效率不高,因為如果我沒記錯的話,我將數據庫訪問了3次。 我想做的是這樣的:
scope :by_product_type_code, -> (hash) { some_method(hash) }
哈希為: { fridge: 3, car: 6, house: 9 }
並獲得一個ActiveRecord_Relation,其中包含3台冰箱,6輛汽車和9座房屋。
我如何有效地做到這一點?
您可以使用UNION ALL創建查詢,該查詢選擇具有特定product_type_code
記錄,並limit
將其與find_by_sql
一起使用:
{ fridge: 3, car: 6, house: 9 }.map do |product_type_code, limit|
"(SELECT *
FROM products
WHERE product_type_code = '#{product_type_code}'
LIMIT #{limit})"
end.join(' UNION ALL ')
您將有一個類似的查詢:
(SELECT * FROM products WHERE product_type_code = 'fridge'LIMIT 3)
UNION ALL
(SELECT * FROM products WHERE product_type_code = 'car'LIMIT 6)
UNION ALL
(SELECT * FROM products WHERE product_type_code = 'house'LIMIT 9)
@SebastianPalma的答案是最好的解決方案; 但是,如果您正在尋找一種生成該查詢的更“卑鄙”的方式,則可以如下使用arel
:
scope :by_product_type_code, ->(h) {
products_table = self.arel_table
query = h.map do |product_type,limit|
products_table.project(:id)
.where(products_table[:product_type_code].eq(product_type))
.take(limit)
end.reduce do |scope1, scope2|
Arel::Nodes::UnionAll.new(scope1,scope2)
end
self.where(id: query)
end
這將導致子查詢成為where子句的一部分。
要么
scope :by_product_type_code, ->(h) {
products_table = self.arel_table
query = h.map do |product_type,limit|
products_table.project(Arel.star)
.where(products_table[:product_type_code].eq(product_type))
.take(limit)
end.reduce do |scope1, scope2|
Arel::Nodes::UnionAll.new(scope1,scope2)
end
sub_query = Arel::Nodes::As.new(query,products_table)
self.from(sub_query)
end
這將導致子查詢成為數據源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.