6

考慮我有一個15個類別和6的子類別和我有其中i已設置的記錄表中​​的項目,其中i具有以下面的方式來獲取如何打開查詢在rails中高效執行?

category 1 ---> level 1 ---> 3 items with maximum price 
category 1 ---> level 2 ---> 3 items with maximum price 
    ... 
    ... 
    ... 
category 15 ---> level 6 ---> 3 items with maximum price 

@categories.each do |value| 
    @sub-categories.each do |value1| 
     array = Item.find(:all, :conditions => ["customer_id IN (?) AND category_id = ? AND sub-category_id = ?", @customer, value.id, value1.id], :order => 'price DESC', :limit => 3) 
      array.each do |value2| 
        @max_price_item_of_each_customer << value2 
      end 
      end 
     end 

但這這將會花費很多時間。那麼我怎樣才能以這樣的方式改變這個時間呢?任何幫助表示讚賞。

+1

你能不能給一個什麼樣的類別,級別和項目可能是一個具體的例子嗎?我很難理解你的數據結構。 – Matthew

回答

2

這一切都取決於你正在使用記錄的規模,但如果你有合理的設置工作,這應該是更快,會降低你的查詢1。

@customer_id = 1 
@categories = [1, 2, 3] 
@subs  = [4, 5, 6] 

@max_price_item_of_each_customer = [] 
items = Item.where(customer_id: @customer, category_id: @categories, subcategory_id: @subcategories) 
items.group_by{|item| item.category_id}.each_pair do |category_id, category_items| 
    category_items.group_by{|item| item.subcategory_id}.each_pair do |subcategory_id, subcategory_items| 
    @max_price_item_of_each_customer += subcategory_items.sort{|x, y| y.price <=> x.price }.first(3) 
    end 
end 
+0

謝謝,這對我來說是一個小編輯。您在嘗試編輯「@max_price_item_of_each_customer +」後錯過了等號,但我不能這麼做,因爲它是唯一的變化。 – logesh

4

嘗試:

@max_price_item_of_each_customer = [] 
@categories.each do |value| 
     @max_price_item_of_each_customer += Item.find(:all, :conditions => ["customer_id IN (?) AND category_id = ? AND sub-category_id in (?)", @customer, value.id, @sub-categories.map(&:id)], :order => 'price DESC', :limit => 3)    
end 
+0

我會試試這個。但在此之前,請您告訴我如何從每個子類別獲取3個項目。我認爲這會爲每個類別提取3個項目。 – logesh

+0

我試過了,它爲每個類別選擇3個項目,而不是爲每個子類別。謝謝 – logesh

1

如果您使用Postgresql,下面的解決方案可能會工作。

  1. items表中選擇一個組的3點的ID,通過price降序排序,並通過category_idsubcategory_id分組。您可以使用Postgres array_agg在分組後收集項目標識。
  2. 選擇項目行,其中項目ID位於那些分組的項目ID中。在此之後,由category_id上升,subcategory_id上升和下降price

結果是ActiveRecord::Relation命令的結果,這樣你就可以重複的項目照常進行。由於結果已變平(但已按類別,子類別和價格排序),因此您需要自行分隔不同的類別和子類別。

grouped_item_ids = Item.where(customer_id: customer_id). 
    select("items.category_id, items.subcategory_id, (array_agg(items.id order by items.price desc))[1:3] AS item_ids"). 
    group("items.category_id, items.subcategory_id").map {|item| item["item_ids"]} 
@items = Item.where(id: grouped_item_ids.flatten). 
    order("items.category_id ASC, items.subcategory_id ASC, items.price desc") 
1

下面的查詢工作對我來說

@max_price_item_of_each_customer =Item.find_by_sql(["SELECT i1.* FROM item i1 
     LEFT OUTER JOIN item i2 ON (i1.category_id = i2.category_id AND i1.sub-category_id = i2.sub-category_id AND i1.id < i2.id) 
     WHERE i1.customer_id IN (?) AND i1.category_id IN (?) 
     GROUP BY i1.id HAVING COUNT(*) < 3 
     ORDER BY price DESC", @customer, @categories.map(&:id)])