Дата между датами, игнорированием года

Какой лучший (самый быстрый) подход для сравнения, если дата находится в диапазоне дат независимо от года?

таблица "даты":

    some_column| since        | upto        |  
    -----------|--------------|-------------|
   'foo'       | '2011-05-01' | '2013-06-01'|

Теперь я хочу, чтобы этот запрос возвращал 'foo'

SELECT foo FROM dates WHERE '2014-05-05' BETWEEN `since` AND `upto`

При необходимости я могу изменить тип/формат сохраненных дат в таблице "даты", но я не могу изменить формат даты, который я ввел в запрос, поскольку это значение обычно происходит из другой таблицы (это часть более сложного запроса с использованием объединений).

Ответ 1

Используйте функцию DayOfYear :

 SELECT foo FROM dates WHERE DayOfYear('2014-05-05') 
    BETWEEN DayOfYear('since') AND DayOfYear('upto')

Ответ 2

SELECT foo FROM dates WHERE DATE_FORMAT('2014-01-15', "%m-%d") 
    BETWEEN DATE_FORMAT(`since`,"%m-%d") AND DATE_FORMAT(`upto`,"%m-%d")

Здесь SQL FIDDLE демо

Ответ 3

Так как вы указали, что в ваших данных хранят произвольный год, вы можете продолжать использовать тип DATE. Тогда это сводится к тому, как запросить.

  • Сохраните поля, используя фиксированный произвольный год. Вы должны использовать високосный год для размещения возможностей 29 февраля. Год 2000 работает красиво. (0004 не будет работать, потому что он слишком мал для типа MySQL DATE.)

  • Заменить год любого значения, которое вы запрашиваете, с тем же годом.

  • Рассмотрим диапазоны, которые пересекаются в конце одного года и в следующем. Чтобы полностью ответить на этот вопрос, вам понадобится следующий запрос:

    SET @dt = cast(CONCAT('2000',RIGHT(thesourcedatevalue,6)) as DATE);
    
    SELECT some_column FROM dates
    WHERE (since <= upto AND since <= @dt AND upto >= @dt) OR
          (since > upto AND (since <= @dt OR upto >= @dt))
    

    Вот скрипт SQL, который демонстрирует

  • Для производительности вы должны быть уверены, что есть индекс, который включает в себя поля since и upto.

Ответ 4

После недолгого просмотра в Google и с помощью stackoverlook я натолкнулся на следующие две проблемы:

  • в каком-то году на 1 день больше (29 февраля)
  • Запрашиваемый диапазон (since и upto) может относиться к разным годам, поэтому использование DayOfYear() является проблемой. Это SQL-запрос, который я придумал.

Допустим, у нас есть дата "2014-05-05" для проверки:

SELECT foo FROM 'dates' WHERE
        (
    /*     --------    since and upto are from same year    --------    */
            YEAR('since') = YEAR('date_fin')
            AND (
                (
                    MONTH('since') < "05"
                    OR
                    (
                        MONTH('since') = "05"
                        AND
                        DAY('since') <= "05"
                    )
                ) AND (
                    MONTH('date_fin') < "05"
                    OR
                    (
                        MONTH('date_fin') = "05"
                        AND
                        DAY('date_fin') >= "05"
                    )
                )
            )
        )OR(
    /*     --------    since and upto are from different year    --------    */
            YEAR('since') <> YEAR('date_fin') AND (
                (
                    MONTH('since') < "05"
                    OR
                    (
                        MONTH('since') = "05"
                        AND
                        DAY('since') <= "05"
                    )
                ) OR (
                    MONTH('date_fin') > "05"
                    OR
                    (
                        MONTH('date_fin') = "05"
                        AND
                        DAY('date_fin') >= "05"
                    )
                )
            )
        )