简体   繁体   English

Ruby on Rails:左外部排序

[英]Ruby on Rails: Left Outer Join with Sort

I have a RoR application for sending emails, I have the models Contacts, Recipients, and Users, whereby a user can have many contacts and a contact can have many recipients. 我有一个用于发送电子邮件的RoR应用程序,有“联系人”,“收件人”和“用户”模型,其中一个用户可以有多个联系人,而一个联系人可以有很多收件人。 The data looks like this: 数据如下所示:

 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

What I want to do is on the index page for contacts, display all the contacts belonging to a user allow the user to choose what to order them by, such as name and the amount of emails received. 我想做的是在联系人的索引页面上,显示属于用户的所有联系人,允许用户选择要订购的商品,例如姓名和收到的电子邮件数量。

The problem I have is that I can display all the contacts belonging to a user no problem, but I am struggling to allow a user to sort the contacts by the amount of emails they have received. 我遇到的问题是,我可以毫无问题地显示属于用户的所有联系人,但是我正在努力让用户根据他们收到的电子邮件数量对联系人进行排序。 The amount of emails they have received can be calculated by counting the amount of recipients with the same contact id. 可以通过计算具有相同联系人ID的收件人数量来计算他们收到的电子邮件数量。 The reason I have this problem is because I want to display all the contacts belonging to a user irrespective of whether they have received emails (a contact may have received 0 emails). 我有此问题的原因是因为我想显示属于用户的所有联系人,而无论他们是否已收到电子邮件(联系人可能已收到0电子邮件)。 The code I have tried is: 我尝试过的代码是:

@contacts = Contact.where(user_id: session[:user_id]).all.order(params.fetch(:sort, 'id asc'))

But this doesn't allow a user to sort by the amount of emails the contacts have received. 但是,这不允许用户按联系人收到的电子邮件数量进行排序。

I have also tried this: 我也尝试过这个:

  @contacts = Contact.where(user_id: session[:user_id]).joins(:recipients).group('contacts.id').all.order(params.fetch(:sort, 'id asc'))

But this only displays the contacts who have received emails. 但这仅显示已收到电子邮件的联系人。

And I have also tried this: 我也尝试过这样:

@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')

This displays all contacts who have and have not received emails and allows sorting, but it shows duplicate data. 这将显示所有已收到和尚未收到电子邮件的联系人,并允许进行排序,但是会显示重复数据。 Ie using the above data, if Ben were to look at his contacts (user_id 1) he could see Jack and Jacob, but because Jack has received 3 emails he would see the following: 即使用上面的数据,如果Ben查看他的联系人(user_id 1),他可以看到Jack和Jacob,但是由于Jack收到了3封电子邮件,他将看到以下内容:

First Name:
Jack
Jacob
Jack
Jack
Jack

Is there a way to solve this? 有办法解决吗? Please note that I am currently using the following code on index.html.erb to allow a user to select what they want to order the records by: 请注意,我目前正在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>

In order to do a LEFT OUTER JOIN try this: 为了做一个左外连接尝试这个:

Contact.includes(:recipients).references(:recipients)

Note: This will also preload recipients and add a ton of SQL to the query 注意:这还将预加载收件人并向查询中添加大量SQL

If you also want to do the sorting, then you should be able to do so like this: 如果您还想进行排序,那么您应该可以这样做:

Contact.includes(:recipients).references(:recipients).group("contacts.id, recipients.id").order("COUNT(recipients.id) ASC")

try this. 尝试这个。

@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')

If you want to show the ones that didn't receive email, you need left outer join. 如果要显示未收到电子邮件的邮件,则需要左外部联接。

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM