ОТЛИЧИТЬСЯ И ЗАКАЗАТЬ - PullRequest
       4

ОТЛИЧИТЬСЯ И ЗАКАЗАТЬ

0 голосов
/ 09 февраля 2012

Вот одно сложное соотношение:

У меня следующее отношение AR:

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

@doctor.patients работает как положено, ничего особенного там нет. Но теперь я бы хотел, чтобы пациенты были назначены врачом, назначенным согласно create_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.

Можно ли выбрать всех пациентов для врача с удаленными дублирующимися пациентами, но все еще по порядку самой новой встречи каждого пациента в одном объединенном запросе?

Спасибо за ваши подсказки!

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, поскольку Rails заменяет все предложение select для построения SQL для # count.

Есть ли способ сделать это менее громоздким?

Ответы [ 2 ]

3 голосов
/ 10 февраля 2012

Попробуйте использовать

    MAX(meetings.created_at)

везде. Таким образом, вы получаете уникальные записи пациентов, даже если у пациентов есть несколько встреч. Мой пример выберет самую последнюю встречу. Используйте MIN(meetings.created_at), если вы предпочитаете выбрать первый.

0 голосов
/ 10 февраля 2012

Попробуйте это:

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.*'
...