2017-02-07 9 views
0

私は電子メールを送信するためのRoRアプリケーションを持っています。私はモデルの連絡先、受信者、およびユーザーを持っているので、ユーザーは多くの連絡先を持ち、連絡先は多くの受信者を持つことができます。データは次のようになります。Ruby on Rails:左外部結合と並べ替え

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

これは持っていると受け取っていないメールをしてソートできますが、それは重複したデータを示し、すべての連絡先が表示されます。私。ベンは彼の連絡先を見ていた場合は、上記のデータを使用して(USER_ID 1)彼はジャックとヤコブを見ることができますが、ジャックは3通の電子メールを受信して​​いるので、彼は以下を参照してくださいになります。解決する方法はあり

First Name: 
Jack 
Jacob 
Jack 
Jack 
Jack 

この?

<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> 
+0

受信した電子メールの数を集計(読み込み回数)する必要があります。 g。グループ( 'contacts.id') – engineersmnky

+0

どのようにしてユーザーはそれらを注文できますか? –

+0

あなたは 'order( 'count(recipients.id)ASC')'を意味しますか?それではちょうどそのように – engineersmnky

答えて

1

はこれを試して登録しよう並べ替えを行うと、このようにすることができるはずです:

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

これはうまくいくようですが、注文することはできません。 –

+0

@BenSmith並べ替えを行う方法の例も追加しました。私はこのような動作するクエリをPostgresでテストしました。 – kaspernj

+0

それは素晴らしいです!ありがとうございました! –

0

これを試してみてください。私は現在、彼らがしてレコードを注文したいものを選択するようにユーザーを許可するようにindex.html.erbに次のコードを使用していますのでご注意ください。

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

メールを受信しなかったものを表示する場合は、外部結合が必要です。

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

注:これはまた、受信者をプリロードし、あなたもしたい場合は、クエリ

にSQLのトンを追加しますLEFT OUTERを行うために

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

ありがとうが、これは私にエラーを与えています: 'SQLite3 :: SQLException:そのような列はありません:reci pients.id:SELECT contacts。*、count(recipients.id)as emails_received "連絡先" INNER JOIN "受信者" ON "受信者"。 "contact_id" = "連絡先"。 "id" WHERE "contacts"。 "user_id" =? GROUP BY contacts.id ORDER BY count(reci pients.id)ASC' –

+0

'.order( 'count(reci pients.id)ASC')'を削除して、すべての連絡先を表示するかどうかを確認しました。残念ながら、電子メールを受信して​​いない連絡先は表示されないため、受信者テーブルには表示されません。 –

+0

@BenSmithおっと...私の悪い。それを忘れてしまった。 '.order( 'emails_received ASC')' –

関連する問題