Сделать выборку из диапазона дат без учета года месяца и т/д

Easy_proger

Привет ! вобщем есть база в ней есть записи я покажу пример ----------------------------------------------DATESTART_ID_DF | DATEEND_ID_DF |-----------------------------------------------1984-03-20 08:46 | 1984-03-31 08:46итак что я хочу ) собственно чтобы к примеру сегодня 03-29 получить эту запись то есть смысл в том что если убрать год то текущая дата попадает в диапазон дат но как составить запрос пока не могу придумать ( пробовал через убирание года из DATESTART_ID_DF и сравнивания с текущей датой не чего не вышло ( видимо совсем кривые руки
16 ответов

Easy_proger

Easy_proger,не знаю почему но редактирование поста не работает ! так надо ? вобщем я забыл указать что и как пробовал и в чем собственно не урядица пробовал стандартными средствами через date_format делать так DATE_FORMAT(DATESTART_ID_DF,"%m-%d") <= DATE_FORMAT(NOW(),"%m-%d")в итоге данные не выбираются ! ( кривые руки ? или недопонимания разницы между date и datetime ? ) пробовал через CONCAT(YEAR(DATESTART_ID_DF)) так же не вышло видимо совсем все запущенно ( итак логически как я вижу можно решить через очень большой кастыль через не которое количество выборок к примеру делаем выборку для начала по месяцу через MONTH(DATESTART_ID_DF) <=month... далее если месяц старта меньше то опускаем если же равняется то сверяем дни и т/д/ но это дико по мне ! я не прав ?как бы решить задачу в один запрос ?


Easy_proger

Вероятно, можно гарантировать, что DATESTART_ID_DF < DATEEND_ID_DF ?Тогда просто возьми ТЕКУЩУЮ дату, замени у неё год - на год из DATESTART_ID_DF, и затем проверяй на попадание в диапазон.


Easy_proger

Правда, тут будут проблемы при попадании НГ в диапазон.


Easy_proger

может так
SELECT * FROM date_table
WHERE MONTH() BETWEEN MONTH(DATESTART_ID_DF) AND MONTH(DATEEND_ID_DF) AND
DAY('2012-03-29') BETWEEN DAY(DATESTART_ID_DF) AND DAY(DATEEND_ID_DF)
только индексы работать не будут, со всеми вытекающими последствиями, вместо '2012-03-29' можно указать CURDATE()


Easy_proger

пардонте , ошибка MONTH()->MONTH('2012-03-29')
SELECT * FROM date_table
WHERE MONTH('2012-03-29') BETWEEN MONTH(DATESTART_ID_DF) AND MONTH(DATEEND_ID_DF) AND
DAY('2012-03-29') BETWEEN DAY(DATESTART_ID_DF) AND DAY(DATEEND_ID_DF)


Easy_proger

а в чем будет проявляться не работание индексов ? у меня вобще индексированые эти таблицы Оо может еще какие варианты есть ? не хотелось бы терять функционал (


Easy_proger

индексы по полям DATESTART_ID_DF и DATEEND_ID_DF и не будут работать, потому что mysql не сможет применить функцию DAY MONTH не перебирая данные, что означает полное сканирование,при работе с индексами mysql может "аналитическим путем" определить пределы сканирования - это очень приблизительное описание работы.Для твоей задачи лучше преобразовать колонки с датами в колонки с годами, месяцами и днями .2 колонки с датой->6 колонок INT, индекс делай по дню и месяцу.Если на выходе нужна дата, то можно использовать функции и создавать даты на лету.без индексов сервер вешается


Easy_proger

тогда получается мне нужно будет делать выборку из базы по месяцу и дальше самому разбирать данные ? или можно через sql будет в один запрос сделать ?


Easy_proger

по факту может вообще проще ссобрать все записи и самому в php отсеять не нужные ? или все же можно sql запросом быстрей сделать ? как организовать ?


Easy_proger

забыл добавить не маловажное условие выборка по базе не всегда будет без учета года ! то есть есть переключатель когда с учетом выбирать а когда без !


Easy_proger

Если даты приведены к INTEGER как я говорил выше то
SELECT * FROM date_table
WHERE 
YEAR('2012-03-29') BETWEEN YEAR_START_ID_DF AND YEAR_END_ID_DF AND # ограничение по году
MONTH('2012-03-29') BETWEEN MONTH_START_ID_DF AND MONTH_END_ID_DF AND # ограничение по месяцу
DAY('2012-03-29') BETWEEN DAY_START_ID_DF AND DAY_END_ID_DF #ограничение по дням
ничего разбирать не надо, ограничения по году месяцу или дню добавляешь по мере необходимости,зачем отбор делать внешней программой пускай mysql думает он для этого создан,


Easy_proger

Easy_proger,
SELECT *
FROM `table`
WHERE DATE_FORMAT(NOW(), '%m-%d') BETWEEN DATE_FORMAT(`DATESTART_ID_DF`, '%m-%d') AND DATE_FORMAT(`DATEEND_ID_DF`, '%m-%d')
Это если поля типа DATE. С DATETIME не пробовал, но думаю тоже прокатит.


Easy_proger

SELECT * FROM date_table
WHERE 
YEAR('2012-03-29') BETWEEN YEAR_START_ID_DF AND YEAR_END_ID_DF AND # ограничение по году
MONTH('2012-03-29') BETWEEN MONTH_START_ID_DF AND MONTH_END_ID_DF AND # ограничение по месяцу
DAY('2012-03-29') BETWEEN DAY_START_ID_DF AND DAY_END_ID_DF #ограничение по дням
К сожалению это вообще не будет работать, т.к тут необходимо, чтобы числовые значения month_end и day_end всегда были больше, чем значения month_start и date_start. По понятным причинам этого не будет.
SELECT *
FROM `table`
WHERE DATE_FORMAT(NOW(), '%m-%d') BETWEEN DATE_FORMAT(`DATESTART_ID_DF`, '%m-%d') AND DATE_FORMAT(`DATEEND_ID_DF`, '%m-%d')
А это не работает, если в диапазон попадает новый год. Гуру sql, помогите! Второй день уже бьюсь над этой задачей. Нужно, чтобы запись с диапазоном дат 2004-12-28 — 2005-01-10 попадала в выборку, если now() 2012-12-30, например.


Easy_proger

тогда так
SELECT *
FROM `table`
WHERE 
DATE_ADD(CURDATE(), INTERVAL -YEAR(CURDATE()) YEAR ) 
BETWEEN 
DATE_ADD(`DATESTART_ID_DF`, INTERVAL -YEAR(`DATESTART_ID_DF`) YEAR ) 
AND
DATE_ADD(`DATEEND_ID_DF`, INTERVAL -YEAR(`DATESTART_ID_DF`) YEAR )


Easy_proger

bochkov,Не работает на диапазонах с новым годом


Easy_proger

SELECT *
FROM `table`
WHERE 
DATE_ADD('2012-12-30', INTERVAL -YEAR( '2012-12-30') YEAR ) 
BETWEEN 
DATE_ADD(`DATESTART_ID_DF`, INTERVAL -YEAR(`DATESTART_ID_DF`) YEAR ) 
AND
DATE_ADD(`DATEEND_ID_DF`, INTERVAL -YEAR(`DATESTART_ID_DF`) YEAR )
Все работает, CURDATE() это для примера, надо было на твой parameter заменить