2012-01-05 3 views
1
года

У меня есть таблица closures, которая состоит из времени, когда дело моего клиента закрыт:Сравнение диапазонов DATE полей CurDate() в MySQL без учета

+----+------------+------------+-------------------------------+--------+ 
| id | start_date | end_date | reason      | yearly | 
+----+------------+------------+-------------------------------+--------+ 
| 1 | 2010-12-24 | 2011-01-08 | Holidays      | 1  | 
| 3 | 2011-01-03 | 2011-01-10 | testing purposes    | 1  | 
| 5 | 2001-01-01 | 2001-01-10 | A non-yearly event   | 0  | 
+----+------------+------------+-------------------------------+--------+ 

Я пытался разработать запрос который проверяет, есть ли какие-либо строки в closures, где CURDATE() находится в пределах start_date и end_date. Суть заключается в том, как игнорировать год, если строка отмечена yearly = '1'. Вот что я получил до сих пор:

SELECT `id`,`reason`,`start_date`,`end_date`,`yearly` FROM `closures` 
WHERE (CURDATE() BETWEEN `start_date` AND `end_date`) /* full date with year is compared */ 
OR 
(
    `yearly` = '1' /* look for events marked yearly */ 
    AND 
    (
     (RIGHT(CURDATE() , 5) BETWEEN RIGHT(`start_date` , 5) AND RIGHT(`end_date` , 5)) /* This WORKS for all date ranges marked yearly that do not go through new years */ 
     OR 
     (RIGHT(CURDATE() , 5) >= RIGHT(`start_date` , 5) AND RIGHT(`start_date` , 5) > RIGHT(`end_date` , 5)) /* This DOES NOT catch date ranges that go through new years */ 
    ) 
) 

Запрос показано выше в таблице, я получаю это:

+----+------------------+------------+------------+--------+ 
| id | reason   | start_date | end_date | yearly | 
+----+------------------+------------+------------+--------+ 
| 3 | testing purposes | 2011-01-03 | 2011-01-10 | 1  | 
+----+------------------+------------+------------+--------+ 

Когда я ожидаю, чтобы получить это:

+----+------------------+------------+------------+--------+ 
| id | reason   | start_date | end_date | yearly | 
+----+------------------+------------+------------+--------+ 
| 1 | Holidays   | 2010-12-24 | 2011-01-08 | 1  | 
+----+------------------+------------+------------+--------+ 
| 3 | testing purposes | 2011-01-03 | 2011-01-10 | 1  | 
+----+------------------+------------+------------+--------+ 

Am I по праву отслеживать? Есть ли лучший/более быстрый способ проверки MM-DD значения DATE, чем использование RIGHT()?

Помощь мне так, я не достоин ...

ответ

0

хорошо, я получил его сейчас!

SELECT 
    * 
FROM 
    `closures` 
WHERE 
    IF(`yearly` = '1', 
     (
      IF(LEFT(`start_date`,4) < LEFT(`end_date`, 4), 
       (
        IF(RIGHT(CURDATE(), 4) > RIGHT(`end_date`, 4), 
         (CURDATE() BETWEEN CONCAT(LEFT(CURDATE(), 5), RIGHT(`start_date`, 5)) AND CONCAT((LEFT(CURDATE(), 4) + 1), RIGHT(`end_date`, 6))), 
         (CURDATE() BETWEEN CONCAT((LEFT(CURDATE(), 4) - 1), RIGHT(`start_date`, 6)) AND CONCAT(LEFT(CURDATE(), 5), RIGHT(`end_date`, 5))) 
        ) 
       ), 
       (
        CONCAT(LEFT(`start_date`, 5), RIGHT(CURDATE(), 5)) BETWEEN `start_date` AND `end_date` 
       ) 
      ) 
     ), 
     (
      CURDATE() BETWEEN `start_date` AND `end_date` 
     ) 
    ) 
+0

Это работает, за исключением случаев, когда закрытие начинается в конце декабря и отправляется на определенную дату после 1 января. Конкат будет собирать год с даты начала и MM-DD из CURDATE. Поэтому, если диапазон закрытия был с 2001-12-24 по 2002-01-10, если вы запустили запрос сегодня (2012-01-04), это последнее предложение будет вычисляться до '2001-01-04' BETWEEN '2001 -12-24 'AND' 2002-01-10 ', который не сработает. – AndyPerlitch

+0

да, я видел это .. извините. опубликовано до того, как я проверил. никому больше не дано вам ничего, что вы можете принять? – davogotland

+0

Я проверил это полностью. он также работает правильно, если текущая дата «2011-12-29». он возвращает только первую строку в этом случае. – davogotland

1
SELECT * FROM closures 
WHERE (
CURDATE() BETWEEN 
    IF(yearly=0,start_date,date_add(start_date, INTERVAL year(CURDATE())-year(start_date) YEAR)) 
AND 
    IF(yearly=0,end_date,date_add(date_add(start_date, INTERVAL year(CURDATE())-year(start_date) YEAR), INTERVAL datediff(end_date, start_date) DAY)) 
) OR (
CURDATE() BETWEEN 
    IF(yearly=0,start_date,date_add(date_add(end_date, INTERVAL year(CURDATE())-year(end_date) YEAR), INTERVAL -1*datediff(end_date, start_date) DAY)) 
AND 
    IF(yearly=0,end_date,date_add(end_date, INTERVAL year(CURDATE())-year(end_date) YEAR)) 
) 

должен сделать трюк. Скальный край - это изменение года, поэтому я рассчитываю длину в дни каждого закрытия и 1. добавляю его с соответствующего начального дня текущего года и 2. вычитаю его с соответствующей даты окончания текущего года.

+0

работает красиво! плюс 1 для ловли всех особых случаев. – davogotland

+0

Хм ... Кажется, он ловит нелетние события, которые, если они будут отмечены ежегодно, будут считаться. Поскольку я не очень хорошо знаком с использованием IF в запросах mysql, мне придется некоторое время посмотреть на это, чтобы понять, что происходит. – AndyPerlitch

+0

Не могли бы вы привести пример?С yearly = 0 это означает SELECT * FROM замыкания WHERE (CURDATE() BETWEEN start_date AND end_date) ИЛИ (CURDATE() BETWEEN start_date AND end_date), который, как я полагаю, корректен –

Смежные вопросы