DISTINCT和ORDER

时间:2012-02-09 19:54:46

标签: sql ruby-on-rails ruby-on-rails-3 postgresql arel

这是一个棘手的关系:

我有以下AR关系:

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

@ doctor.patients按预期工作,那里没什么了不起的。但是现在我想让一位医生按照作业的created_at命令(最新的)。

# 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子句。

是否有可能为所有患者取出所有患者,其中重复的患者被移除但仍在每个患者的最新会议中进行一次JOINed查询?

感谢您的提示!

更新

使用Oliver的提示我已经更新了如下关系:

# 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是必要的,因为Rails会替换整个select子句来为#count构建SQL。

有什么方法可以让它不那么笨重?

2 个答案:

答案 0 :(得分:3)

尝试使用

    MAX(meetings.created_at)

无处不在。像这样,即使患者有多次会议,您也会获得独特的患者记录。我的例子将选择最新的会议。如果您希望选择第一个,请使用MIN(meetings.created_at)

答案 1 :(得分: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.*'