2012-02-09 12 views
0

は、ここに1人のトリッキーな関係です。しかし、今私は割り当てのcreated_atによって注文された医者のための患者を取得したい(最新のもの)。はDISTINCTとORDER

# Doctor 
has_many :patients, through: :meetings, uniq: true, order: 'meetings.created_at DESC' 
has_many :meetings 

今では(Postgresの9日)は動作しません: "ERROR:SELECT DISTINCTのために、表現BY ORDERは、選択リストに表示されなければなりません"。よしさんがそれをやらせる:

# Doctor 
has_many :patients, through: :meetings, select: 'DISTINCT patients.*, meetings.created_at', order: 'meetings.created_at DESC' 
has_many :meetings 

これは再び動作しますが、DISTINCTが全体SELECT句に取り組んでいるので、患者はもう一意ではありません。

重複した患者を取り除いた医師のためにすべての患者をフェッチすることは可能ですが、1人のJOINされたクエリで各患者の最新の会議で依頼しますか?

あなたのヒントをありがとう!

UPDATE:オリバーのヒントを使用して

次のように私は関係を更新しました:

# Doctor 
has_many :patients, 
    through: :assignments, 
    select: 'patients.*, MAX(assignments.created_at) AS last_assignment', 
    group: 'patients.id', 
    order: 'last_assignment DESC', 
    counter_sql: proc { "SELECT COUNT(DISTINCT patients.id) FROM patients INNER JOIN assignments ON patients.id=assignments.patient_id WHERE assignments.doctor_id=#{id}" } 

RailsはのためのSQLを構築するために全体のselect句を置き換えるため、別々のcounter_sqlが必要であることがapears #カウント。

これを小さくする方法はありますか?

答えて

3

どこでも
MAX(meetings.created_at) 

を使用してみてください。このように、患者が複数の会議を開いていても、独自の患者記録が得られます。私の例では、最新の会議を選択します。代わりに最初のものを選択する場合は、MIN(meetings.created_at)を使用してください。

has_many :patients, 
    through: :meetings, 
    order: 'meetings.created_at DESC', 
    conditions: 'row_number() over(partition by meetings.doctor_id, meetings.patient_id) order by meetings.created_at desc) = 1' 

別の試み:

+0

を、これは – araqnid

+0

おかげでaraqnid "*最新*会議" のロジックをコード化するために、いくつかの明確化を追加しました。 –

+0

私はあなたのヒントを質問に取り入れました。 AR関係でMIN()を使用するには、さらにいくつかの追加が必要ですが、動作します。 (私はまもなくあなたの答えを受け入れるでしょう) – svoop

0

はこのお試しください...

has_many :patients, 
    through: :meetings, 
    order: 'max(meetings.created_at) DESC', 
    group: 'patients.*', 
    select: 'patients.*' 
+0

これは動作しません:エラー:WHERE句でウィンドウ関数が許可されていません – svoop