【问题标题】:MySQL date comparison queryMySQL日期比较查询
【发布时间】:2019-05-28 12:36:37
【问题描述】:

我的数据库中有这张表:

table t

id   |  a   | b  | date_x

1    |  81  | 12 | 2018-03-16
2    |  9   | 54 | 2025-04-21
3    |  81  | 67 | 2018-03-16
4    |  763 | 81 | 2018-03-16
5    |  90  | 22 | 2025-12-08

date_x 是日期类型

我想选择 a = 81 或 b = 81 且 date_x 在 2019-05-28 之前的行。

所以我在 MySQL Workbench 中执行以下查询:

SELECT * FROM t
WHERE a = '81' OR b = '81'
AND date_x > '2019-05-28';

这是我得到的:

1    |  81  | 12 | 2018-03-16
3    |  81  | 67 | 2018-03-16

我希望 2018-03-16 不迟于 2019-05-28 。此外,为什么只返回 2 行?在 date_x 列中还有另一个相同日期。

这个查询返回相同的结果:

SELECT * FROM t
WHERE a = '81' OR b = '81'
AND date_x > str_to_date('2019-05-28', '%Y-$m-%d');

我为调试执行了以下查询:

SELECT * FROM t
WHERE a = '81' OR b = '81'
AND date_x < '2019-05-28';

SELECT * FROM t
WHERE a = '81' OR b = '81'
AND date_x < str_to_date('2019-05-28', '%Y-$m-%d');

然后两者都按预期返回:

1    |  81  | 12 | 2018-03-16
3    |  81  | 67 | 2018-03-16
4    |  763 | 81 | 2018-03-16

我阅读了以下问答,但我仍然遗漏了一些东西:

有什么提示吗?谢谢

【问题讨论】:

    标签: mysql database select


    【解决方案1】:

    您的查询格式为

    SELECT * FROM t WHERE condition_a OR condition_b AND condition_c

    AND 运算符的绑定比 OR 更强,因此您最终会得到

    SELECT * FROM t WHERE condition_a OR (condition_b AND condition_c)

    这就是我认为混乱的来源。与日期无关。

    【讨论】:

    • 这是在 obviuos 的限制。感谢您帮助聚焦正确的点
    【解决方案2】:

    您应该将select 括在括号中。因为它,你会得到WHERE a = '81' OR (b = '81' AND date_x &gt;'2019-05-28')

    SELECT * FROM t
    WHERE (a = '81' OR b = '81')
    AND date_x > '2019-05-28';
    

    【讨论】:

    • 这是在 obviuos 的限制。感谢您帮助聚焦正确的点
    【解决方案3】:

    改写成

    SELECT * FROM t
    WHERE a = '81' AND date_x > '2019-05-28'
    UNION ALL 
    SELECT * FROM t
    WHERE b = '81' AND date_x > '2019-05-28'
    

    可能更有意义,尤其是当您考虑性能时,请考虑此表结构和索引..

    CREATE TABLE t (
      `id` INTEGER,
      `a` INTEGER,
      `b` INTEGER,
      `date_x` VARCHAR(10)
      , INDEX(a, date_x)
      , INDEX(b, date_x)
    );
    

    作为

    SELECT * FROM t
    WHERE (a = '81' OR b = '81')
    AND date_x > '2019-05-28';
    

    无法使用索引请参阅demo,并且很可能最终会扫描完整的表/索引文件。

    由于 MySQL 优化器是基于成本的,我还包括 this 以确保第一个查询的完整扫描不是简单地由低数量的记录触发..
    但很明显,第二个查询有更稳定的计划..

    如果被索引,我相信 Oracle 数据库会在此优化器中直接重写 ORUNION ALL。由于 MySQL 归 Oracle 所有,我希望他们也将它添加到 MySQL 中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 2013-09-16
      • 2020-04-21
      • 1970-01-01
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多