【问题标题】:Inconsistent MySQL date comparison YYYY/MM/DD vs YYYY-MM-DDMySQL 日期比较 YYYY/MM/DD 与 YYYY-MM-DD 不一致
【发布时间】:2010-09-22 03:38:46
【问题描述】:

我有一个 MySQL (v 5, MyISAM) 查询,它根据日期字符串格式返回不同的行。

(1) IFNULL(date1, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) > '2008-10-31 23:59:59'
(2) IFNULL(date1, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) > '2008/10/31 23:59:59'

(3) date1 > '2008-10-31 23:59:59'
(4) date1 > '2008/10/31 23:59:59'

'/' vs '-' on RHS of '>' 比较运算符。

(1) 75,098 rows *expected*
(2) 0 rows *DIFFERENCE*
(3) 199 rows *simple case as expected*
(4) 199 rows *simple case as expected*

问题 - 为什么?

【问题讨论】:

    标签: mysql


    【解决方案1】:

    简短回答: 使用CAST(... AS DATE)

    长答案:

    来自MySQL DATE type

    允许使用“宽松”的语法:任何 标点符号可以用作 日期部分之间的分隔符或 时间部分。例如,'98-12-31 11:30:45','98.12.31 11+30+45', '98/12/31 11*30*45' 和 '98@12@31 11^30^45' 是等价的。

    在示例 1 和 2 中,您使用的是 ADDDATE... 这将始终返回带有“-”分隔符的日期,无论输入格式如何:

    +-----------------------------------------------+
    | ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY) |
    +-----------------------------------------------+
    | 2008-11-01 23:59:59                           |
    +-----------------------------------------------+
    

    您还使用了 IFNULL,它会丢失类型信息,因此当您比较它时,它会作为字符串进行比较。

    你可以做的就是把它转回一个日期:

    mysql> SELECT IFNULL(null, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) > '2008/10/31 23:59:59';
    +-------------------------------------------------------------------------------------+
    | IFNULL(null, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) > '2008/10/31 23:59:59' |
    +-------------------------------------------------------------------------------------+
    |                                                                                   0 |
    +-------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    
    
    mysql> SELECT CAST(IFNULL(null, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) AS DATE) > '2008/10/31 23:59:59';
    +---------------------------------------------------------------------------------------------------+
    | CAST(IFNULL(null, ADDDATE('2008/10/31 23:59:59',INTERVAL 1 DAY)) AS DATE) > '2008/10/31 23:59:59' |
    +---------------------------------------------------------------------------------------------------+
    |                                                                                                 1 |
    +---------------------------------------------------------------------------------------------------+
    

    【讨论】:

    • 糟糕。我完全错过了答案中的字符串日期转换:-)
    【解决方案2】:

    我对 mysql 了解不多,但是否有可能基于“/”的日期被解释为“YYYY/DD/MM”,因此完全无效?在 SQL Server 中,我希望在这种情况下出现异常,但如果 mysql 替换为某种“无效日期”值,则可能可以解释差异。

    YYYY-MM-DD 是官方 ISO 格式。 YYYY/MM/DD 我没听说过。

    【讨论】:

      【解决方案3】:

      参考简答:使用 CAST(... AS DATE)

      LHS 是 (1) 和 (2) 相同的是 RHS 改变评估并且是一个字符串。

      参考基于“/”的日期。

      如果 '2008/10/31 23:59:59' 是一个无效日期,它将在选项 (1)、(3)、(4) 中失败,这是唯一成功的选项。 如果 ''2008-10-31 23:59:59' 是无效的日期,它将在选项 (1)、(3) 中失败。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-30
        • 1970-01-01
        相关资源
        最近更新 更多