Comments 34
ну и велосипед…
а strtotime вам чем не угодил???
а strtotime вам чем не угодил???
Как именно strtotime здесь использовать?
Перекинуть из представления SQL в UNIXTIME, приплюсовать количество секунд: N * 3600 * 24 и перекинуть обратно в SQL-формат. В итоге получите конец интервала.
у вас же в системе известно текущие дата и время? думаю что да :)
к пример у вас $curDate это оно и есть, $interval — это период а $shift — сдвиг от текущего времени в сек. тогда:
$curDate = date('Y-m-d H:i:s');
$startDate = strtotime($curDate) + $shift;
$endDate = $startDate + $interval;
прводим к читабельному формату:
$sStartDate = date('md', $startDate);
$sEndDate = date('md', $endDate);
ну а дальше в ваш первый запрос подставляете эти значения. только преобразовывать дату на лету не самый лучший вариант для мускула, лучше сделать отдельную колонку для даты в формате DATE_FORMAT(birthday,'%m%d') и при вставке вносить туда уже подготовленные данные. + сделать по ней индекс. будет летать. проверено на табл со 100 млн. записями, правда на постгре.
к пример у вас $curDate это оно и есть, $interval — это период а $shift — сдвиг от текущего времени в сек. тогда:
$curDate = date('Y-m-d H:i:s');
$startDate = strtotime($curDate) + $shift;
$endDate = $startDate + $interval;
прводим к читабельному формату:
$sStartDate = date('md', $startDate);
$sEndDate = date('md', $endDate);
ну а дальше в ваш первый запрос подставляете эти значения. только преобразовывать дату на лету не самый лучший вариант для мускула, лучше сделать отдельную колонку для даты в формате DATE_FORMAT(birthday,'%m%d') и при вставке вносить туда уже подготовленные данные. + сделать по ней индекс. будет летать. проверено на табл со 100 млн. записями, правда на постгре.
можно интервалы задавать не в секундах а промежутками:
$interval = '+1 month';
$interval = '+1 month';
Это именно то, что у меня написано. Только Вы перевели на чистый PHP без ZF. И про индексы с отдельным столбцом я писал.
Если Вы делали выборку ближайших дней рождения, то поделитесь.
Дни рождения в ближайшие 5 дней:
select
u.birthdate
from user__accounts as u
where
datediff(
date_add(
u.birthdate,
interval year(from_days(datediff(current_date, u.birthdate)))+1 year
),
current_date
) < 5
select
u.birthdate
from user__accounts as u
where
datediff(
date_add(
u.birthdate,
interval year(from_days(datediff(current_date, u.birthdate)))+1 year
),
current_date
) < 5
Вроде нормально. А как со скоростью выполнения? У меня во WHERE вроде попроще условие.
К сожалению, ответить точно насчет скорости не смогу, пример из проекта, где всего ~2500 записей в таблице, mysql-клиент выдает 0.00 sec.
Но, если рассуждать логически, выполняются все те же действия, что и у Вас, только средствами mysql, что, по моему подозрению, быстрее чем zf+mysql.
Но, если рассуждать логически, выполняются все те же действия, что и у Вас, только средствами mysql, что, по моему подозрению, быстрее чем zf+mysql.
Правильность что-то тоже вызывает сомнения. Проверю, когда интервал пересекает НГ.
Дни рождения в ближайшие 3 дня:
Вычисление возраста:
или
SELECT * FROM `users`
WHERE
DAYOFYEAR(`birthdate`) >= DAYOFYEAR(CURDATE()) AND
DAYOFYEAR(`birthdate`) < DAYOFYEAR(CURDATE() + 3)
Вычисление возраста:
SELECT ROUND(DATEDIFF(CURDATE(), `birthdate`) / 365) AS `age` FROM `users`
или
SELECT TIMESTAMPDIFF(YEAR,`birthdate`, CURDATE()) AS `age` FROM `users` (спасибо glock18)
Как то так, чем то похоже на вариант aubt, но чуть другой:
где 5 — нужное число дней
последнюю сстроку можно просто скриптом вычислить отправив в запрос просто числа с которым и сравнивать.
писал без проверки (не на чем), может где ошибся, но идея наверно понятна
SELECT * FROM user__accounts
WHERE
UNIX_TIMESTAMP( -- конвертируем в секунды
DATE_ADD(birthday, -- прибавляем к днюхе разницу лет
INTERVAL
(YEAR(NOW())-YEAR(birthday))
YEAR
)
)
BETWEEN (UNIX_TIMESTAMP(NOW())) AND (UNIX_TIMESTAMP(NOW()) + 5*24*60*60)
где 5 — нужное число дней
последнюю сстроку можно просто скриптом вычислить отправив в запрос просто числа с которым и сравнивать.
писал без проверки (не на чем), может где ошибся, но идея наверно понятна
Ваш запрос рабочий, однако конвертация в секунды имеет один недостаток — в выборку не попадают сегодняшние дни рождения, посколько unix_timestamp(now()) даже при совпадении дат отличается от unix_timestamp(birthdate) в большую сторону на текущее время.
Хотя это легко исправимо, думаю Ваш запрос все-таки, скажем так, элегантнее :)
Хотя это легко исправимо, думаю Ваш запрос все-таки, скажем так, элегантнее :)
функция вычисления возраста у вас тоже неправильная!
уменьшать кол-во лет надо только тогда когда текущий день и месяц года еще не перевалил за день месяц дня рождения.
а у вас наоборот.
исправьте на:
if (date('md', $birth) > date('md', $now)) {
уменьшать кол-во лет надо только тогда когда текущий день и месяц года еще не перевалил за день месяц дня рождения.
а у вас наоборот.
исправьте на:
if (date('md', $birth) > date('md', $now)) {
Если большая таблица и посещений много — лучше поступить по другому (сделано так в highload проекте).
Добавляем к юзерам дополнительную колонку birthday_in типа smallint.
Создаём процедуру, которая про планировщику задачь чуть после 24:00 пересчитывает для каждого юзера колонку birthday_in и днях до дня рождения. Учитываем високосные года, переходы и.т.д.
В итоге выборка дней рождений сводится к проверке WHERE birthday_in < 4 если надо показывать за 3 дня до самого дня рождения + вы можете легко помечать юзеров, у которых день рождения сегодня.
Добавляем к юзерам дополнительную колонку birthday_in типа smallint.
Создаём процедуру, которая про планировщику задачь чуть после 24:00 пересчитывает для каждого юзера колонку birthday_in и днях до дня рождения. Учитываем високосные года, переходы и.т.д.
В итоге выборка дней рождений сводится к проверке WHERE birthday_in < 4 если надо показывать за 3 дня до самого дня рождения + вы можете легко помечать юзеров, у которых день рождения сегодня.
Sign up to leave a comment.
Выбор дней рождения на MySQL + мелочи