【问题标题】:Efficient SELECT query to find records within a month高效的SELECT查询查找一个月内的记录
【发布时间】:2015-06-10 00:08:45
【问题描述】:

我有一个包含多个日期类型字段的 MySQL 数据库表。我需要对此表执行不同的 SELECT 查询,但我不确定哪种方法最适合查找同一个月的记录。

我知道我可以做到以下几点:

SELECT *
  FROM table
 WHERE MONTH(somedate) = 5
   AND YEAR(somedate) = 2015

但我一直在阅读,效率不高,我应该使用实际日期,即

SELECT *
  FROM table
 WHERE somedate BETWEEN '2015-05-01' AND '2015-05-31'

但是,我所拥有的只是月份和年份作为来自 PHP 的变量。如果我选择第二个选项,如何轻松快速地计算当月的最后一天?

【问题讨论】:

  • 我发现 between 在我的数据库上比 month/yearlike 慢。月/年 = Showing rows 0 - 29 (77 total, Query took 0.0825 sec)。之间 = Showing rows 0 - 29 (77 total, Query took 0.1059 sec)。喜欢 =Showing rows 0 - 29 (77 total, Query took 0.0815 sec)。这是在 7k 行表上。但是,该线程指向另一个方向。 dba.stackexchange.com/questions/96245/…
  • MySQL 可以有效利用前导列为somedate 的索引。如果您没有这样的索引,那么您可以创建一个,例如CREATE INDEX ON table (somedate)。只要查询返回的行数少于表中的 10%,索引就会使查询速度更快。将函数包裹在 somedate 列上,MySQL 必须在表中的每一行上评估这些函数。
  • 使用EXPLAIN查看执行计划。对于性能比较,请确保查询结果不是从查询缓存返回的。有几种方法可以做到这一点,例如SQL_NO_CACHE命中,在查询中包含用户定义的变量,禁用查询缓存等(我们实际上将我们的 MySQL 服务器配置为缓存 only 查询,其中包括SQL_CACHE 提示,因此我们控制可以缓存哪些查询,并防止结果被我们不需要缓存的查询刷新。)

标签: mysql date


【解决方案1】:

不要计算当月的最后一天。改为计算下个月的第一天。

你的查询可以是这样的

WHERE t.mydatetimecol >= '2015-05-01'
  AND t.mydatetimecol  < '2015-05-01' + INTERVAL 1 MONTH

请注意,我们正在进行小于比较,而不是“小于或等于”...这对于比较 TIMESTAMP 和 DATETIME 列非常方便,其中可以包含时间部分.

请注意,BETWEEN 比较是“小于或等于”。为了得到与上面查询等效的比较,我们需要做

WHERE t.mydatetimecol
      BETWEEN '2015-05-01' AND '2015-05-01' + INTERVAL 1 MONTH + INTERVAL -1 SECOND 

(这里假设DATETIMETIMESTAMP的分辨率下降到一秒。在其他数据库中,例如SQL Server,分辨率小于一秒,所以我们有可能错过值为'2015-05-31 23:59:59.997'的行。比较下个月的第一天,我们没有这样的问题...&lt; '2015-06-01'

无需自己计算月份或日期,让 MySQL 为您计算。如果您想将月份加 1,则必须处理从 12 月到 1 月的翻转,并增加年份。 MySQL 已经内置了所有这些。

【讨论】:

    【解决方案2】:

    date('t', strtotime("$year-$month-01")) 将给出该月的天数

    【讨论】:

    • 最后问了这个特定任务的“如何做”问题。我认为 BETWEEN 的表现会更好,如果其他人没有先了解,以后可能会详细说明。
    猜你喜欢
    • 2012-11-30
    • 2023-01-30
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多