【问题标题】:MySQL Query for certain date rangeMySQL查询特定日期范围
【发布时间】:2013-09-03 23:59:49
【问题描述】:

我有以下表格数据:

Table: Seasons                
id   from        to
---------------------------
1    2013-08-30  2013-09-04
2    2013-09-05  2013-09-08
3    2013-09-09  2013-09-20

我需要运行一个查询,返回某个日期范围内的所有记录,例如:返回所有受2013-09-04 to 2013-09-05影响的记录

应该是这样的

date  range:                    | 09-04 - 09-05| 
seasons:          08-30 - 09-04 | 09-05 - 09-08     | 09-09 - 09-20

所以它应该返回前 2 条记录。 我已经尝试使用 BETWEEN 进行查询,但它接缝我需要建立几个案例 - 还是有更简单的方法? 谢谢

【问题讨论】:

    标签: mysql date


    【解决方案1】:

    令人惊讶的是,近两年没有人注意到这一点,但其他答案都是错误的,因为他们没有考虑开始日期和结束日期都超出的情况搜索范围的范围。考虑这是日期的范围:

    start_date <<---------------------------- date range --------------------------->> end_date
    

    这是我们的搜索范围:

    start_date <<---------------------------- date range --------------------------->> end_date
    
                     start_search <<-------- search range -------->> end_search
    

    搜索应该给我们一个肯定的结果,因为它们相交。但是如果你使用其他答案,你会得到一个否定的结果,因为start_dateend_date 都不在start_searchend_search 之间。

    为了得到解决方案,让我们画出所有 4 种可能的模式交集:

     start_date > end_date
    
    start_search > end_search
    start_date > end_date
    
                   start_search > end_search
    start_date > end_date
    
                     start_search > end_search
     start_date > end_date
    
    start_search > end_search

    您可以OR所有 4 种可能的情况来获得直截了当的解决方案:

    select*from table where
    
       /* 1st case */ start_date between start_search and end_search         
    or /* 2nd case */  end_date  between start_search and end_search         
    or /* 3rd case */ (start_date <= start_search and end_date >= end_search)
    or /* 4th case */ (start_date >= start_search and end_date <= end_search)
    
    /* the 4th case here is actually redundant since it is being covered by the 1st and 2nd cases */
    

    一个不太直接的解决方案是:

    从表中选择*
    
        start_search 和 end_search 之间的 start_date /* 涵盖第 1 和第 4 种情况 */
    或 start_search 在 start_date 和 end_date 之间 /* 涵盖第 2 和第 3 种情况 */

    尝试使用上面的图表将其可视化。


    如果我们尝试从上面的 4 个图表中推断出一个模式,我们可以看到在交叉路口,end_date 始终是 &gt;= start_search,而另一方面,start_date 始终是 &lt;= end_search。事实上,进一步可视化,我们可以看到当这两个条件成立时,我们不可能没有交集

    因此,另一种解决方案很简单:

    select*from table where
    
    end_date >= start_search && start_date <= end_search
    

    而且这个解决方案的优点是我们只需要 2 次比较。相比之下,“OR Everything”方法需要 2 到多达 8 次(3 + 3 + 2)比较。 (每个between 调用都包含3 comparisons。)

    【讨论】:

    • 我想链接另一个问题,其中包含一个更简单的(答案)[stackoverflow.com/questions/2545947/….它是关于 foins 之类的: WHERE new_start existing_start;哪个更有效率。感谢@Gibbok、Xavi Lopez 和 Steve Lillis 的建议。
    • @IvanRodriguezTorres,奇怪的是,在受到"rectangle overlaps" 解决方案的启发后,我以为我已经使用 2-comparison 解决方案提交了更新。无论如何感谢您的通知,我已经重新提交了更新。
    • 答案现在很完美。谢谢!
    • @Pacerier 怎么样 SELECT * FROM table WHERE AND ( ( start_date BETWEEN start_search AND end_search ) OR ( end_date BETWEEN start_search AND end_search ) OR ( start_search BETWEEN start_date AND end_date ) OR ( start_search BETWEEN start_date AND end_date ) )
    【解决方案2】:

    尝试:

    SELECT *
    FROM `Seasons`
    WHERE (`from` BETWEEN '2013-09-04' AND '2013-09-05' OR `to` BETWEEN '2013-09-04' AND '2013-09-05')
    

    【讨论】:

    • 谢谢。这正是我在两个单独的字段中寻找日期范围的内容。
    • @LouieMiranda,这个解决方案是有缺陷的,因为它只涵盖了 4 个可能场景中的 3 个场景。换句话说,如果您使用此代码,您得到误报。
    【解决方案3】:

    这应该可以工作

    SELECT *
    FROM `Seasons`
    WHERE (date_field BETWEEN '2010-01-30 14:15:55' AND '2010-09-29 10:15:55')
    

    **确保日期为mysql默认格式(yyyy-mm-ff hh:mm:ss)

    【讨论】:

    • 这显然行不通,你只打了一个between 电话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 2011-01-01
    • 2021-01-03
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多