Pull to refresh

Comments 34

ну и велосипед…
а 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 млн. записями, правда на постгре.
можно интервалы задавать не в секундах а промежутками:
$interval = '+1 month';
сорри, отправилось рано, так вот:
$interval = '+1 month';
$shift = '+1 day';
$curDate = date('Y-m-d H:i:s');
$startDate = strtotime($curDate. ' '. $shift);
$endDate = strtotime($interval, $curDate);
ну а дальше как и в пред. примере.
высокосные нам не страшны ни в первом ни во втором случаях
Это именно то, что у меня написано. Только Вы перевели на чистый 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
Вроде нормально. А как со скоростью выполнения? У меня во WHERE вроде попроще условие.
К сожалению, ответить точно насчет скорости не смогу, пример из проекта, где всего ~2500 записей в таблице, mysql-клиент выдает 0.00 sec.

Но, если рассуждать логически, выполняются все те же действия, что и у Вас, только средствами mysql, что, по моему подозрению, быстрее чем zf+mysql.
ZF тут совсем не причем, вопрос в построении запроса.
UFO just landed and posted this here
Правильность что-то тоже вызывает сомнения. Проверю, когда интервал пересекает НГ.
Я проверил.
Подставьте вместо current_date '2009-12-31', например.
DATEDIFF(date_add(u.birthday, INTERVAL YEAR(FROM_DAYS(DATEDIFF(CURRENT_DATE, u.birthday)))+1 YEAR), CURRENT_DATE)
вот эта конструкция для сегодняшних дней рождения выдает либо 0 либо 365
странно, похоже в зависимости от високосности
Дни рождения в ближайшие 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, но чуть другой:

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) в большую сторону на текущее время.

Хотя это легко исправимо, думаю Ваш запрос все-таки, скажем так, элегантнее :)
UNIX_TIMESTAMP(NOW())UNIX_TIMESTAMP(DATE(NOW()))
и недостаток исчез :)

Да, но я бы предпочел unix_timestamp(current_date) :)
Логично :)

Ну и правую границу тоже надо чуть переделать соответственно
UFO just landed and posted this here
UFO just landed and posted this here
функция вычисления возраста у вас тоже неправильная!
уменьшать кол-во лет надо только тогда когда текущий день и месяц года еще не перевалил за день месяц дня рождения.
а у вас наоборот.
исправьте на:
if (date('md', $birth) > date('md', $now)) {
UFO just landed and posted this here
UFO just landed and posted this here
Круто! У вас на сайте новорожденные до года и еще не родившиеся зарегистрированы?
UFO just landed and posted this here
Если большая таблица и посещений много — лучше поступить по другому (сделано так в highload проекте).

Добавляем к юзерам дополнительную колонку birthday_in типа smallint.
Создаём процедуру, которая про планировщику задачь чуть после 24:00 пересчитывает для каждого юзера колонку birthday_in и днях до дня рождения. Учитываем високосные года, переходы и.т.д.

В итоге выборка дней рождений сводится к проверке WHERE birthday_in < 4 если надо показывать за 3 дня до самого дня рождения + вы можете легко помечать юзеров, у которых день рождения сегодня.
Sign up to leave a comment.

Articles