簡體   English   中英

活動記錄,SQL:選擇並計算與聯接條件的關聯

[英]Active record, SQL: select and count association with joins condition

我在優化SQL查詢以及利用活動記錄生成查詢時遇到問題。 它涉及選擇關聯的ID和計數以及帶有變量輸入的條件連接。 此外,我還不能使用where語句,因為我想要的結果還沒有任何關聯。 我的模型如下

class Vote < ActiveRecord::Base
  belongs_to :user
  belongs_to :venue
  belongs_to :catering_event
  validates :catering_event_id, uniqueness: { scope: :user_id }
end

class Venue < ActiveRecord::Base
  has_many :votes
  has_many :catering_events, through: :votes
  has_many :users, through: :votes
end

class CateringEvent < ActiveRecord::Base
  has_many :votes
  has_many :venues, through: :votes
  has_many :users, through: :votes  
end

我所擁有的是場地,catering_events(簡稱事件)和用戶。 用戶可以為每個事件投1票,其中投票是用戶,選擇事件的場所(user_id,container_id和catering_event_id)。

在顯示事件頁面上,我想顯示所有場所及其投票數,其中沒有投票數的場所顯示的投票數為0,這是我試圖通過一個查詢來完成的。 我之所以能夠利用where子句,是因為我的嘗試過濾掉了尚未投票的場所。

我目前有兩個功能解決方案,而我都不滿意。 第一個是直接的find_by_sql查詢; 但是我必須半破解返回值,因為find_by_sql僅返回模型當前具有的屬性。

對於我當前的數據:

#<Vote:0x007fb9f681ac38 id: 1, user_id: 2, venue_id: 3, catering_event_id: 1>,
#<Vote:0x007fb9f681aa58 id: 2, user_id: 1, venue_id: 2, catering_event_id: 1>,
#<Vote:0x007fb9f681a8f0 id: 3, user_id: 1, venue_id: 1,  catering_event_id: 2>

我的功能find_by_sql查詢:

sql =     
"SELECT COUNT(votes.id) AS id, venues.id AS venue_id 
FROM venues 
LEFT OUTER JOIN votes ON votes.venue_id = venues.id 
AND votes.catering_event_id = ? 
LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id 
GROUP BY venues.id"

=> "SELECT COUNT(votes.id) AS id, venues.id AS venue_id FROM venues LEFT OUTER JOIN votes ON votes.venue_id = venues.id AND votes.catering_event_id = ? LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id GROUP BY venues.id"

pry(main)> Vote.find_by_sql [sql, '1']
Vote Load (9.0ms)  SELECT COUNT(votes.id) AS id, venues.id AS venue_id FROM venues LEFT OUTER JOIN votes ON votes.venue_id = venues.id AND votes.catering_event_id = '1' LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id GROUP BY venues.id

=> [
  #<Vote:0x007fb9f33ca8c0 id: 0, venue_id: 1>, 
  #<Vote:0x007fb9f33ca668 id: 1, venue_id: 2>, 
  #<Vote:0x007fb9f33ca258 id: 1, venue_id: 3>
]

這將返回餐飲事件1的所有場所及其票數。但是,我必須將表決數命名為模型上的某個屬性,從中我將其稱為find_by_sql,並且由於表決具有3個條件,因此無法向其中添加1個模型投票計數屬性。 當我嘗試將計數命名空間命名為自定義字段時,我沒有像文檔所說的那樣獲得@attributes具有的值,它只是忽略了該值:

Vote Load (0.7ms)  SELECT COUNT(votes.id) AS vote_count, venues.id AS venue_id 
FROM venues 
LEFT OUTER JOIN votes ON votes.venue_id = venues.id 
AND votes.catering_event_id = '1' 
LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id 
GROUP BY venues.id
=> [
  #<Vote:0x007fb9f31d29a0 id: nil, venue_id: 1>, 
  #<Vote:0x007fb9f31d2248 id: nil, venue_id: 2>, 
  #<Vote:0x007fb9f31d1c58 id: nil, venue_id: 3>
]

我已經解決的第二個解決方案涉及使用活動記錄來進行查詢,但是我還沒有弄清楚如何使用變量catering_event_id正確清理joins語句:(我實際上沒有在新行上運行它,但是出於可讀性考慮,我將其拆分了達)

Venue.select('venues.id as venue_id')
  .joins('LEFT OUTER JOIN votes ON votes.venue_id = venues.id AND votes.catering_event_id = 2')
  .joins('LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id').group('venues.id')
  .count('votes.id')
(0.6ms)  SELECT COUNT(votes.id) AS count_votes_id, venues.id AS venues_id FROM `venues` LEFT OUTER JOIN votes ON votes.venue_id = venues.id AND votes.catering_event_id = 2 LEFT OUTER JOIN catering_events ON catering_events.id = votes.catering_event_id GROUP BY venues.id
=> {1=>1, 2=>0, 3=>0}

注意第一個joins語句,我不得不在其中硬編碼2:

AND votes.catering_event_id = 2

正如我想出了如何將變量傳遞給活動記錄joins語句。

總而言之,我試圖使用帶有find_by_sql的直接sql或活動記錄(我的偏好是活動記錄)執行單個查詢,以選擇所有場所以及變量catering_event的投票計數。 我更願意調整我當前的解決方案之一,以允許find_by_sql返回自定義的以名稱分隔的屬性,或者弄清楚如何正確地將一個joins語句傳遞給一個內插的/清理過的變量。

我在Rails 4.2.1和ruby 2.2.0上

答案最終出現在find_by_sql命令中。

盡管它沒有在返回值中顯示它,但是使用查詢中的AS關鍵字創建了一個虛擬屬性。 現在,我可以執行SELECT COUNT(votes.id) AS vote_count ,盡管返回對象未顯示該屬性的vote_count ,但它們會對此做出響應。

例如

query = Vote.find_by_sql([sql, '1'])
query.map(&:vote_count)
=> [0,1,1]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM