2012-05-14 4 views
4

У меня есть база данных с датами рождения и именами пользователей. Я хочу выбрать всех пользователей, у которых был день рождения/имена с 7 дней до 7 дней в будущем, этот выбор работает, но я не знаю, как решить проблему с пользователями, у которых есть день рождения/имена 31.12. например. PHP вернет «ПОЛЬЗОВАТЕЛЬ имел день рождения за 3 дня до этого», этот выбор работает хорошо всего за 7 дней до конца года и 7 дней после нового года. Большое вам спасибо за помощь.MySQL за 7 дней до события и через 7 дней после события

SELECT `name`, `surname`, `gender`, ('birthday') AS event, 
    DATEDIFF(NOW(), DATE(REPLACE(`birthday`, YEAR(`birthday`), YEAR(NOW())))) AS diff 
FROM `users` 
WHERE DATEDIFF(NOW(), DATE(REPLACE(`birthday`, YEAR(`birthday`), YEAR(NOW())))) 
BETWEEN -7 AND 7 
UNION 
    SELECT `name`, `surname`, `gender`, ('namesday') AS event, 
    DATEDIFF(NOW(), DATE(REPLACE(`namesday`, YEAR(`namesday`), YEAR(NOW())))) AS diff 
    FROM `users` 
    WHERE DATEDIFF(NOW(), DATE(REPLACE(`namesday`, YEAR(`namesday`), YEAR(NOW())))) 
    BETWEEN -7 AND 7 
+0

Существует 'DAYOFYEAR'. Но как вы собираетесь справляться с високосными годами (люди, имеющие день рождения 29 февраля, теперь 29 февраля?)? Все это нужно уточнить и выполнить тщательно, я видел, что веб-сайты были отключены из-за таких ошибок, последний раз в этом году ... 29 февраля ;-) – krlmlr

+0

Я думаю, что DATEDIFF (X, Y) работает как TO_DAYS (X) -TO_DAYS (Y), поэтому существует 29.2. включая –

+0

Да. Но, опять-таки, любой код для обработки этого, вероятно, должен рассмотреть четыре (!) Случая: {день рождения (не) 29 февраля} x {'NOW()' is not not Feb 29th}. Кроме того, вычисление отличается в зависимости от того, является ли текущий год високосным годом или нет. Трудно получить это прямо в элегантной манере. – krlmlr

ответ

1

Хороший вопрос. Вот что я сделал до сих пор. Я не уверен, что это прекрасно, но это может быть хорошим началом. Попробуйте.

select *, 
if(right(birthday,5)>=right(curdate(),5),concat(year(curdate()),'-',right(birthday,5)),concat(year(curdate()+interval 1 year),'-',right(birthday,5))) as next_birthday, 
if(right(birthday,5)<right(curdate(),5),concat(year(curdate()),'-',right(birthday,5)),concat(year(curdate()-interval 1 year),'-',right(birthday,5))) as prev_birthday 
from users 
having next_birthday 
between curdate() - interval 7 day and curdate() + interval 7 day 
or prev_birthday 
between curdate() - interval 7 day and curdate() 
+0

Право есть любая процедура? –

+0

right - это строковая функция, которая возвращает вам последние пять символов строки (в данном случае даты рождения mm-dd) –

+1

это немного запутанно, существуют существующие методы, которые будут делать это, не полагаясь на разбор даты вручную , – kirbs

0

Brute метод силы будет рассчитать свой диф за год-1,, год + 1, а затем проверить, если любой из этих 3-х сумм удовлетворяет ваше состояние.

Не так грубой силой было бы сделать разницу между первым и первым января и рассчитать годы соответственно этому.

Интересная проблема, я вернусь, если я придумаю что-то еще.

1

Я думаю, что это довольно прямолинейно, используйте to_days(). Этот способ зависит от календаря, установленного в БД, поэтому вам не нужно беспокоиться о високосных годах.

select 
    `name`, `surname`, `gender`, ('birthday') AS event, 
    to_days(concat(year(current_date()),'-',month(`birthday`), '-',day_of_month(`birthday`))) as current_yr_bday 
FROM `users` 
WHERE 
    to_days(concat(year(current_date()),'-',month(`birthday`), '-',day_of_month(`birthday`))) between to_days(date_sub(current_date() interval 7 days) and to_days(date_add(current_date() interval 7 days 
Смежные вопросы