Такая, вот, хитрая задача у меня периодически всплывает.
Пусть есть таблица с некоторыми объектами. И есть таблица выставления оценок за эти объекты. Ну, пусть так:
objects:
id: int
title: string
object_date: timestamp
votes:
object_id: int
score: int
vote_date: timestamp
Нужно выбрать объекты, имеющие оценку выше определённой — это не вопрос.
SELECT object_id FROM votes WHERE SUM(score) > 10;
А вот дальше — проблемная задача. Нужно отсортировать объекты не абы как, а по дате, когда сумма превысила порог вывода (10 в нашем примере).
Сейчас я реализую параллельной таблицей best_objects, типа:
best_objects:
object_id: int
pin_date: timestamp
ну и вывод из неё, соответственно.
Проблема в том, что приходится вести лишнюю таблицу, фактически избыточную. И, не дай бог, меняются критерии — нужно всё пересчитывать, «имитируя» обработку голосов по мере добавления.
Есть ли у кого мысли, как этот вопрос можно решить изящнее?
Примеры из практики, если абстрактно описание непонятно: например, нужно вывести поток лучших сообщений форума, но с тем, чтобы сообщения, которые «добрали» рейтинг, оказывались сверху, даже если они старые. Попал в поток — твоё место (дата попадения) в нём фиксировано. Если сортировать по дате самого сообения, то старые сообщения, набравшие пороговую оценку, окажутся незамеченными в глубине списка. Если сортировать по дате последней оценки, то одни и те же сообщения будут всплывать по мере новых голосов за них. И т.д.
Для упрощённого варианта, когда нет поля score и мы учитываем только сами голоса, приходит в голову мысль, что нужно как-то сгрупировать votes по object_id, отсортировать по дате голоса и отрезать limit'ом по пороговому числу. Максимальное значение даты в группе и будет датой попадения в избранные. Но даже такой упрощённый вариант слабо представляю как реализовать на практике. Можно, наверное, извратиться с парой вложенных SELECT'ов, но это ужасно. Может, есть какой-то более изящный вариант?