Как выбрать всех пользователей, у которых день рождения в определенный период, без учета года?
Нагуглил в интернете сотню решений, но у всех есть какие-то нюансы работы.
Основная проблема в том, что мне нужно выбрать всех пользователей, у которых дни рождения в указанный период без учета года.
Например, выбрать всех, у кого ДР между 10 января и 25 января и не важно какой год рождения.
Пытался остановиться на чем-то подобном, но работает все равно не верно. SELECT `ID` FROM `users` WHERE DATE_FORMAT(`BIRTHDAY`,'%d.%m') BETWEEN '01.01' AND '19.01'
Выбирает пользователей с ДР:
01.01
05.01
16.01
А при таком условии BETWEEN '01.02' AND '15.01'
05.01 и 16.01 все равно остаются.
Подскажите, пожалуйста, как сделать это правильно?
Самый простой способ — как указал blo. Только вместо %c я бы написал %m, а при переходе через границу года нужно добавить ещё одно условие в where.
И необходимо помнить, что это будет фулскан таблицы с преобразованиями строк. Поэтому, чтобы это работало быстро, надо либо создать функциональный индекс (но mysql вроде не умеет их), либо денормализовать таблицу, введя дополнительное служебное поле с индексом, и занося в него преобразованную дату рождения (%m%d) при вставке и обновлении.
Я бы вообще посоветовал так не делать, приведенный вами запрос не должен работать с индексом, т.к. вы запросили DATE_FORMAT для данных, что приведет к обработке всех выражений, сделайте отдельное поле, в которое и кидайте данные как вам надо, для заполнения можно триггер использовать, а по нему уже искать.
SELECT ID FROM users WHERE DATE(BIRTHDAY) BETWEEN '1900-01-01' AND '3000-12-31';
SELECT ID FROM users WHERE DATE(BIRTHDAY) >= '1900-01-01' AND DATE(BIRTHDAY) <= '3000-12-31';
В обоих случаях индекс использоваться не будет, если нужен индекс — приводим к типу DATE
Сделайте колонку с порядковым номером дня в году для дня рождения. Тогда сможете индекс сделать и условие простое будет. Ну только, как указали выше, отдельно учесть переход через границу года
Сталкивался с похожим…
Проблема была только в том, что некоторые записи имеют год а некоторые нет.
Выбираем только месяц+день и ставим год теперешний. Эту переменную ставим индексом и фильтруем как хотим.
От селектов DATE_FORMAT отказался так как база очень больших размеров, и выборка по int индексу в разы быстрее.