Хотя SQL довольно прост, когда речь идет об ответах на вопросы типа «когда была самая последняя публикация за каждый день?» это не очень прямолинейно, когда вы спрашиваете «какая была самая последняя запись за каждый день?»
Вы не можете получить последнее сообщение за каждый день, не используя вложенный SELECT (или несколько операторов SQL). Это может работать для вас (используйте Post.find_by_sql или подобное):
SELECT P.*, M.just_day, M.max_created_at
FROM posts P
JOIN (
SELECT date(P2.date) AS just_day, MAX(P2.created_at) AS max_created_at
FROM posts P2
P.location_id='12345' AND P.published=true
GROUP BY date(P2.date)
) AS M
ON AND M.max_created_at = P.created_at
WHERE P.location_id='12345' AND P.published=true
Приведенного выше оператора SQL должно быть достаточно , если , вы можете быть уверены, что два столбца не будут иметь одинаковое значение в столбце create_at. Если вы не можете гарантировать уникальность в созданном столбце at, то вам нужно либо отфильтровать дубликаты в Ruby (это не должно быть слишком неэффективно, потому что, по-видимому, вы все равно будете перебирать список), либо вам нужно будет выполнить N +1 SQL операторов. (На самом деле вы можете делать выборки для каждой строки, но AFAIK так же неэффективен, как N + 1 SQL-операторы.)
Вот как вы можете удалить дубликаты во время цикла:
last_post = nil
posts.each do |post|
unless post.just_day == last_past.try(:just_day)
# Do stuff
last_post = post
end
end
Тем не менее, вы могли бы написать это просто с помощью Ruby / ActiveRecord, если у вас есть достаточно дней, чтобы SELECT для каждого дня не был слишком плохим:
days = Post.group("date(date)")
posts = days.each { |day| Post.order('created DESC').where("date(day) = ?", day) }
Если вы используете нумерацию страниц (скажем, 10 элементов на страницу), то для каждой страницы потребуется 11 операторов SQL. Не идеи, а простота может стоить неэффективности.
Честно говоря, если вы ожидаете, что этот запрос будет выполняться часто и с достаточно большим набором данных, тогда я предлагаю вам добавить логический столбец с именем most_recent. Последнее сообщение из прошлых дней не изменится. Вам нужно только беспокоиться о сообщениях с сегодняшнего дня. Просто настройте задачу cron для запуска через несколько минут после окончания дня, чтобы обновить значение за последний день. Если вы хотите что-то более современное, вы можете запускать задание cron каждые 5 минут. Или, если вам нужно в режиме реального времени, добавьте обратный вызов after_save, чтобы установить для Most_recent значение false для всех сегодняшних сообщений, которые не являются текущими.
Этот вопрос похож на: MySQL: получение наибольшего количества очков для пользователя