2012-02-09 32 views
0

這裏有一個棘手的關係:DISTINCT和ORDER

我有以下AR關係:

# Doctor 
has_many :patients, through: :meetings, uniq: true 
has_many :meetings 

@ doctor.patients按預期工作,沒有什麼壯觀那裏。但是現在我想讓病人去找一位醫生(由最新的第一個)創作出來的醫生。

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

現在不工作(在Postgres的9): 「錯誤:SELECT DISTINCT,ORDER BY表達式必須出現在選擇列表」。好吧,讓我們做到這一點:

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

這再次工作,但患者不是唯一的了,因爲DISTINCT正在對整個SELECT子句。

是否有可能將所有患者轉移到一位醫生身上,但重複的患者被移除,但是仍然由一名聯合查詢中的每位患者的最新會議排序?

感謝您的提示!

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}" } 

單獨counter_sql apears因爲Rails的替換整個SELECT子句中生成SQL爲是必要的#計數。

任何方法可以使這個更輕鬆?

回答

3

使用

MAX(meetings.created_at) 

到處嘗試。像這樣,即使患者有幾次會議,您也可以獲得獨特的患者記錄。我的示例將選擇最新的會議。如果您想選擇第一個,請使用MIN(meetings.created_at)

+0

...因爲這個編碼 「* *最新會議」 – araqnid 2012-02-09 21:20:08

+0

感謝araqnid,增加了一些澄清的邏輯。 – 2012-02-09 21:26:10

+0

我已經提出了你的問題。在AR關係中使用MIN()需要再添加幾個,但它起作用。 (我很快就會接受你的回答。) – svoop 2012-02-10 09:03:54

0

試試這個:

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' 

另一種嘗試:

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

這不起作用:錯誤:WHERE子句中不允許使用窗口函數 – svoop 2012-02-10 08:02:20