【问题标题】:select * from table where datetime in month (without breaking index)select * from table where datetime in month(不破坏索引)
【发布时间】:2013-07-05 15:46:49
【问题描述】:

我有一堆带时间戳的行(使用“日期时间”数据类型)

我想选择时间戳在特定月份内的所有行。

该列已编入索引,因此我不能执行 MONTH(timestamp) = 3,因为这会使该索引无法使用。

如果我有年份和月份变量(在 perl 中),是否有一些可怕的 SQL 我可以使用:

timestamp BETWEEN DATE($year, $month, 0) AND DATE($year, $month, 31);

但更好,并且确实有效?

【问题讨论】:

  • 我可以假设您想要所有年中某个月份的所有行吗?

标签: sql mysql optimization


【解决方案1】:

我实际上会同意你提出的想法;可能有一点不同:

select *
from your_table 
where date_field >= '2010-01-01'
    and date_field < '2010-02-01'

(当然,$year$month 的使用取决于你)


请注意 &lt; '2010-02-01' 部分:如果您的日期包含时间,则可能需要考虑这一点。

例如,如果您有一个日期类似于 '2010-01-31 12:53:12' 的行,您可能希望选择该行 - 默认情况下,'2010-01-31' 表示 '2010-01-31 00:00:00'


也许这看起来并不“好看”;但它会工作;并使用索引...这是我遇到此类问题时通常使用的解决方案。

【讨论】:

    【解决方案2】:

    这实质上是 Pascal MARTIN 的 answer,但避免了明确知道下一年/月是什么(因此您不必在 $month == 12 时增加年份并环绕 $month):

    my $sth = $mysql_dbh->prepare(<<__EOSQL);
    SELECT ...
      FROM tbl
     WHERE ts >= ? AND ts < (? + INTERVAL 1 MONTH)
    __EOSQL
    
    my $yyyymm = $year . '-' . sprintf('%02d', $month);
    
    $sth->execute($yyyymm, $yyyymm);
    

    对于额外的积分,您也可以这样做:

    ... WHERE ts BETWEEN ? AND (? + INTERVAL 1 MONTH - INTERVAL 1 SECOND)
    

    - INTERVAL 1 SECOND 会将上限从 DATE 强制转换为设置为一天的最后一秒的 DATETIME/TIMESTAMP 类型,正如 Pascal 所指出的,这是您想要的上限。

    【讨论】:

      【解决方案3】:

      如果您需要每年的同一个月,那么您拥有的索引将无济于事,再多的 SQL 语法技巧也无济于事

      另一方面,如果您需要特定年份的一个月,那么任何带有日期范围的查询都应该这样做

      【讨论】:

        【解决方案4】:

        另一种选择是在存储月份的表中添加一个额外的列,预先计算。那只是一个简单的 int 列,并且对索引很简单。除非您要处理 kajillion 行,否则 unsigned tiny int 的额外空间可以忽略不计(每行一个字节 + db 开销)。

        与时间戳列保持同步需要一些额外的工作,但这就是触发器的用途。

        【讨论】:

          【解决方案5】:

          WHERE MONTH(`date`) = '$month' AND YEAR(`date`) = '$year'怎么样

          【讨论】:

            猜你喜欢
            • 2011-10-07
            • 2011-04-06
            • 1970-01-01
            • 2017-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-12
            相关资源
            最近更新 更多