Добрый вечер!
Пишу модуль, который будет отображать блок со ссылками на две ноды (матчи), которые надо выбирать, отталкиваясь от сегодняшней даты. Первая должна быть самой «свежей» из прошедших, вторая — ближайшей из грядущих. Пример: Есть матчи 3 января, 7 января, 10 января, 13 января и 15 января. Мне нужно, чтобы запрос 11 января выдёргивал из базы только матчи 10 и 13 января и т.д, 12 января — тоже самое, а 14 января уже матчи 13 и 15 января и т.д.
Вопрос первый: как сделать это одним запросом к базе? Решил пойти через ORDER BY ABS(DATEDIFF(gamedatetime,CURDATE())) (модуль разницы между датой матча и текущим днём) LIMIT 2, но не уверен, что это наилучший вариант, хотя ответы он мне выдаёт правильные.
Вопрос второй: будет ли подобный запрос кошерным (да ещё и с использованием функций MySQL по обработке дат и математическими операциями) или лучше всё-таки разделить на два?
Вопрос третий: как бы вы посоветовали правильно кэшировать блок с таким запросом, результат которого может оставаться неизменным в течение нескольких дней (так как перерывы между играми бывают большими)?
В принципе, можно добавить к моему запросу что-нибудь типа WHERE gamedatetime (поле даты матча) BETWEEN DATE_SUB(CURDATE(), INTERVAL 10 DAY) AND DATE_ADD(CURDATE(), INTERVAL 10 DAY) для того, чтобы сузить поле деятельности запроса, но, как я понимаю, это даст только лишнюю нагрузку на базу.
Заранее спасибо за ответы.
Комментарии
ИМХО конечно, но мне кажется два запроса с с лимитом, отработают быстрее чем один со всяческими вычислениями
Ага. Вот мне тоже почему-то так кажется. Но пока мои два запроса получаются тоже с вычислениями — WHERE gamedatetime < CURDATE() ORDER BY DATEDIFF(gamedatetime,CURDATE()) DESC для события в прошлом и WHERE gamedatetime > CURDATE() ORDER BY DATEDIFF(gamedatetime,CURDATE()) для события в будущем. И что-то у меня туго соображает голова — не могу сообразить, как оптимизировать эти запросы.
Кстати, я уже нашёл потенциальную возможность, чтобы мой запрос через ABS(DATEDIFF(gamedatetime,CURDATE())) отработал не так, как мне надо — если даты событий 3 января, 10 января, 13 января (а такое вполне часто бывает, что между матчами сначала перерыв в неделю, а потом всего пару дней), то 9 января запрос выдаст мне 10 января и 13 января, как наименьшие по модулю.
Можно попробовать без лимитов и ордер бай
пример для ноды
( select min(created) dt from {node} where created>1220446629 ) s1 ON n1.created=s1.dt
union all
select n2.nid,n2.created from {node} n2 inner join
( select max(created) dt from {node} where created<1220446629 ) s2 ON n2.created=s2.dt
только надо учитывать если есть «точно» совпадающие даты то вернется больше 2-х записей,
тут вместо числа [1220446629] будет конечно текущая дата ну а вместо created ваша дата в базе, ну и таблицы соответственно ваши
Спасибо, интересный вариант. Но разве вложенный запрос заставит базу работать меньше, чем Ордер в связке с Лимитом?
Ну точно сказать не могу (не знаю как там оптимизатор в MySQL устроен), но насколько я знаю базы данных, ORDER BY почти всегда ведет к фулскану, и только потом к выборке будет применен лимит ...
агрегатные же функции (если по агрегируемому полю есть индекс) скорее всего возьмут адрес записи из индекса,
ну а вообще я не теоретик, если я не прав гуру меня поправят
Надо будет попробовать через EXPLAIN прогнать оба запроса, может быть он даст хотя бы приблизительный ответ на то, что использовать лучше, если здесь не найдётся гуру MySQL.