0

我有模特這樣的多態關係如何獲得點擊率最高的記錄,並至少具有一個子級資源將被包括

class Level1 
has_and_belongs_to_many :level2s 
has_many :resources ,:as => :mediable 
end 

class Level2 
    has_and_belongs_to_many :level1s 
    has_many :level3s 
    has_many :resources ,:as => :mediable 
end 

class Level3 
    belongs_to :level2 
    has_many :resources ,:as => :mediable 
end 

class Resource 
    belongs_to :mediable , polymorphic: true 
    has_many :resources ,:as => :mediable 
    has_many :clicks ,:as => :mediable 
end 

class click 
    belongs_to :clickable , polymorphic: true 
end 

當用戶添加在1級/級別2/3級的資源(圖像或媒體)我顯示這些媒體的地方,用戶可以點擊這個,每次點擊我保存在點擊表中的條目

現在我需要在level1的顯示頁面上的用戶時,我需要顯示level1s和level2s的前50名資源在點擊計數和至少一個資源將從數據庫中提取

我要嘗試這樣的:

Resource.select("resources.*, count(clicks.id) as click_counts") 
      .joins("INNER JOIN clicks ON clicks.clickable_id = resources.id AND clicks.clickable_type='Resource'") 
      .where("(resources.mediable_id IN(1) AND resources.mediable_type='Level1') OR (resources.mediable_id IN(1, 2, 3, 4, 5) AND resources.mediable_type='Level2')") 
      .group("resources.id") 
      .order("click_counts").limit(50) 

它會返回與1級及其相關level2s排名前50位的資源,但沒有不能保證我有相關的level2的至少一個資源。

你能幫助我,我怎麼能做到這一點

有可能性的資源從來沒有點擊,但是我必須讓資源以及我需要至少一個資源爲每個級別 所以我認爲內加入應該切換到左外

回答

1

如果不是你的問題做一點點額外的計算,你可以很容易地實現它:

resources = Resource.select("resources.*, count(clicks.id) as click_counts") 
      .joins("INNER JOIN clicks ON clicks.clickable_id = resources.id AND clicks.clickable_type='Resource'") 
      .where("(resources.mediable_id IN(1) AND resources.mediable_type='Level1') OR (resources.mediable_id IN(1, 2, 3, 4, 5) AND resources.mediable_type='Level2')") 
      .group("resources.id") 
      .order("click_counts").limit(50) 

unless resources.pluck(:mediable_type).include? 'Level2' 

    resources = resources.limit(49) + Resource.select("resources.*, count(clicks.id) as click_counts") 
      .joins("INNER JOIN clicks ON clicks.clickable_id = resources.id AND clicks.clickable_type='Resource'") 
      .where("resources.mediable_id IN(1, 2, 3, 4, 5) AND resources.mediable_type='Level2'") 
      .group("resources.id") 
      .order("click_counts").limit(1) 
end 

否則,你可以像這樣的東西(未測試)嘗試:

sub_select = "(
    SELECT resources.*, count(clicks.id) as click_counts, 1 as SortKey 
    FROM resources 
    INNER JOIN clicks ON clicks.clickable_id = resources.id AND clicks.clickable_type='Resource' 
    WHERE resources.mediable_id IN(1, 2, 3, 4, 5) AND resources.mediable_type='Level2' 
    GROUP BY resources.id 
    ORDER BY mediable_type, click_counts 
    LIMIT 1 

    UNION ALL 

    SELECT resources.*, count(clicks.id) as click_counts, 2 as SortKey 
    FROM resources 
    INNER JOIN clicks ON clicks.clickable_id = resources.id AND clicks.clickable_type='Resource' 
    WHERE (resources.mediable_id IN(1) AND resources.mediable_type='Level1') OR (resources.mediable_id IN(1, 2, 3, 4, 5) AND resources.mediable_type='Level2') 
    GROUP BY resources.id 
    ORDER BY SortKey, mediable_type, click_counts) as t" 

select_sql = "SELECT DISTINCT resources.*, click_counts FROM #{sub_select} LIMIT 50" 

results = ActiveRecord::Base.connection.select_all(select_sql).rows # array 
results_ordered = results.sort { |a, b| a.last <=> b.last } # sort by clicks_count 

注:

  • SortKey額外的屬性保證了查詢訂購
  • UNION ALL不排除任何重複的記錄。因此,我們需要添加一個DISTINCTresources.*, click_counts列刪除不可能性重複記錄(第一「級別2」)

希望它能幫助!

+0

看起來不錯看起來不錯,我會嘗試 – Thorin

相關問題