2013-08-22 41 views
0

我有以下SQL查詢:Rails的ActiveRecord的連接查詢的條件

SELECT campaigns.* , campaign_countries.points, offers.image 
FROM campaigns 
JOIN campaign_countries ON campaigns.id = campaign_countries.campaign_id 
JOIN countries ON campaign_countries.country_id = countries.id 
JOIN offers ON campaigns.offer_id = offers.id 
WHERE countries.code = 'US' 

這工作得很好。我想它的軌道的活動記錄版本的一些事情,如:

Campaign.includes(campaign_countries: :country).where(countries: {code: "US"}) 

上面的代碼運行或多或少正確的查詢(沒有嘗試,包括報價表),問題是返回的結果是運動的集合對象,因此這顯然不包括點

我的表是:

campaigns --HAS_MANY--< campaign_countries --BELONGS_TO--< countries 
campaigns --BELONGS_TO--> offers 

寫這個SQL的AR版本有什麼建議?我不想在我的代碼中使用SQL語句。

回答

0

如果您有活動,您可以使用campaign.campaign_countries獲取關聯的campaign_countries,並從中獲取積分。

> campaign.campaign_countries.map(&:points) 
=> [1,2,3,4,5] 

同樣您將能夠從優惠關係中獲得圖片。

編輯:

好吧,我想現在我知道發生了什麼事。您可以使用joinsselect從連接表中獲取附加字段的對象。

cs = Campaign.joins(campaign_countries: :country).joins(:offers).select('campaigns.*, campaign_countries.points, offers.image').where(countries: {code: "US"}) 

你可以通過自己的名字Campaign對象

cs.first.points 
cs.first.image 

但可以肯定比引用其他字段,額外的列名不與一些主表的字段或對象的方法重疊。

編輯2:

一些調查研究後,我來到了結論,我的第一個版本是針對這種情況實際上是正確的。我將使用我自己的控制檯作爲例子。

> u = User.includes(:orders => :cart).where(:carts => { :id => [5168, 5167] }).first 
> u.orders.length # no query is performed 
=> 2 
> u.orders.count # count query is performed 
=> 5 

,所以當你在國內使用includes與條件,在campaign_countries只存儲campaign_countries是滿足您的條件。

+0

我需要的積分只針對國家 – Rakesh

+0

我認爲我的答案現在應該滿足您,但這不是我想的Railish方式。 –

+0

現在(第二次編輯後)我很確定這是你在找什麼 –

0

試試這個:

Campaign.joins([{ :campaign_countries => :countries}, :offers]).where('`countries`.`code` = ?', "US") 
+0

加入時出現的結果與包含 – Rakesh

+1

兩者不同。 Checkout [rails-include-vs-joins](http://stackoverflow.com/questions/1208636/rails-include-vs-joins)和[railscast](http://railscasts.com/episodes/181-include- VS-聯接) – manoj2411

1

我一些如何得到這個工作沒有SQL,但肯定它的窮人的解決方案:

在我的控制器

我:

campaigns = Campaign.includes(campaign_countries: :country).where(countries: {code: country.to_s}) 
render :json => campaigns.to_json(:country => country) 

在戰役模式:

def points_for_country country 
    CampaignCountry.joins(:campaign, :country).where(countries: {code: country}, campaigns: {id: self.id}).first 
    end 

    def as_json options={} 
    json = { 
     id: id, 
     cid: cid, 
     name: name, 
     offer: offer, 
     points_details: options[:country] ? points_for_country(options[:country]) : "" 
    } 
    end 

和campaign_countries模型:

def as_json options={} 
    json = { 
     face_value: face_value, 
     actual_value: actual_value, 
     points: points 
    } 
    end 

爲什麼這不是很好的解決方案?因爲它會調用太多的查詢: 1.它執行第一次加入時調用查詢以獲取特定於國家/地區的活動列表 2.對於在第一個查詢中找到的每個活動,它將在campaign_countries表上調用另一個查詢以獲取運動和國家。

這是壞的,壞的和壞的解決方案。任何建議,以改善這一點?