[英]Ruby on Rails: Left Outer Join with Sort
我有一個用於發送電子郵件的RoR應用程序,有“聯系人”,“收件人”和“用戶”模型,其中一個用戶可以有多個聯系人,而一個聯系人可以有很多收件人。 數據如下所示:
User
ID Name
1 Ben
2 Emily
3 Brian
Contact
ID Name User_ID
1 Jack 1
2 Joe 2
3 Chloe 2
4 Jacob 1
5 Trevor 3
Recipient
ID Contact_ID Email_ID (not relevant for this question)
1 1 2
2 1 1
3 4 5
4 1 6
5 2 8
我想做的是在聯系人的索引頁面上,顯示屬於用戶的所有聯系人,允許用戶選擇要訂購的商品,例如姓名和收到的電子郵件數量。
我遇到的問題是,我可以毫無問題地顯示屬於用戶的所有聯系人,但是我正在努力讓用戶根據他們收到的電子郵件數量對聯系人進行排序。 可以通過計算具有相同聯系人ID的收件人數量來計算他們收到的電子郵件數量。 我有此問題的原因是因為我想顯示屬於用戶的所有聯系人,而無論他們是否已收到電子郵件(聯系人可能已收到0電子郵件)。 我嘗試過的代碼是:
@contacts = Contact.where(user_id: session[:user_id]).all.order(params.fetch(:sort, 'id asc'))
但是,這不允許用戶按聯系人收到的電子郵件數量進行排序。
我也嘗試過這個:
@contacts = Contact.where(user_id: session[:user_id]).joins(:recipients).group('contacts.id').all.order(params.fetch(:sort, 'id asc'))
但這僅顯示已收到電子郵件的聯系人。
我也嘗試過這樣:
@contacts = Contact.where(user_id: session[:user_id]).joins("LEFT OUTER JOIN contacts ON contacts.id = recipients.contact_id").all.order('max(recipients.contact_id) DESC')
這將顯示所有已收到和尚未收到電子郵件的聯系人,並允許進行排序,但是會顯示重復數據。 即使用上面的數據,如果Ben查看他的聯系人(user_id 1),他可以看到Jack和Jacob,但是由於Jack收到了3封電子郵件,他將看到以下內容:
First Name:
Jack
Jacob
Jack
Jack
Jack
有辦法解決嗎? 請注意,我目前正在index.html.erb
上使用以下代碼,以允許用戶選擇要通過以下方式對記錄進行排序的方式:
<form>
Order By:
<select name="sort">
<option value="firstname ASC">First Name (A - Z)</option>
<option value="firstname DESC">First Name (Z - A)</option>
<option value="surname ASC">Surname (A - Z)</option>
<option value="surname DESC">Surname (Z - A)</option>
<option value="email ASC">Email (A - Z)</option>
<option value="email DESC">Email (Z - A)</option>
<option value="max(recipients.contact_id) ASC">Emails Recieved (Low - High)</option>
<option value="max(recipients.contact_id) DESC">Emails Recieved (High - Low)</option>
<option value="updated_at ASC">Date Updated (Oldest First)</option>
<option value="updated_at DESC">Date Updated (Newest First)</option>
</select>
<button>
Go
</button>
</form>
為了做一個左外連接嘗試這個:
Contact.includes(:recipients).references(:recipients)
注意:這還將預加載收件人並向查詢中添加大量SQL
如果您還想進行排序,那么您應該可以這樣做:
Contact.includes(:recipients).references(:recipients).group("contacts.id, recipients.id").order("COUNT(recipients.id) ASC")
嘗試這個。
@contacts = Contact.select('contacts.*, count(recipients.id) as emails_received')
.where(user_id: session[:user_id])
.joins(:recipients)
.group('contacts.id')
.order('emails_received ASC')
如果要顯示未收到電子郵件的郵件,則需要左外部聯接。
@contacts = Contact.select('contacts.*, count(recipients.id) as emails_received')
.where(user_id: session[:user_id])
.joins('LEFT OUTER JOIN recipients ON recipients.contact_id = contacts.id)
.group('contacts.id')
.order('emails_received ASC')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.