日期之间的日期,忽略年份

问题描述 投票:8回答:4

如果日期独立于年份在日期范围内,最好的(最快的)比较方法是什么?

表格“日期”:

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

现在我希望此查询返回'foo'

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

[如果需要,我可以更改“日期”表中存储日期的类型/格式,但是我不能更改输入查询的日期格式,因为该值通常来自另一个表(这是使用联接的更复杂查询的一部分) 。

mysql date between
4个回答
4
投票

使用DayOfYear功能:

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

3
投票
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演示


1
投票

由于您已表示可以在数据中存储任意年份,因此可以继续使用DATE类型。然后就归结为如何查询。

  • 使用固定的任意年份存储字段。您应该使用a年来适应2月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))
    

    Here is a SQL Fiddle that demonstrates

  • 为了提高性能,您应该确保有一个包含sinceupto字段的索引。


0
投票

经过简短的google-look和stackoverlook之后,我遇到了以下2个问题:

  • 一年多了1天(2月29日)
  • 要求的范围(sinceupto)可以属于不同的年份,这使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"
                    )
                )
            )
        )
© www.soinside.com 2019 - 2024. All rights reserved.