【问题标题】:SQL - Date Between (xxxx-06-21 and xxxx-09-21)SQL - 日期介于(xxxx-06-21 和 xxxx-09-21)之间
【发布时间】:2011-09-29 02:14:57
【问题描述】:

如何在 MySQL 中使用 BETWEEN 函数来搜索任何年中的日期,但介于特定的日/月到特定的日/月之间?或者如果无法使用 BETWEEN,我还能如何完成它?

为了更具描述性,我正在尝试向我的照片存档网站添加季节性搜索。因此,如果用户选择搜索“夏季”照片,它将搜索 6 月 21 日至 9 月 21 日之间拍摄的照片,但可以是任何年份。

如果嘉士伯做SQL,我想会是:)

WHERE date BETWEEN 'xxxx-06-21' AND 'xxxx-09-21'

非常感谢

【问题讨论】:

    标签: mysql sql search


    【解决方案1】:

    在其他地方给出的解决方案WHERE date.MONTH() || date.DAY() BETWEEN '0621' AND '0921' 是一个很好的解决方案(它非常值得支持,因为它适用于大多数 MySQL 数据库)但我想指出它(以及大多数涉及每行函数的查询) ) 不能很好地扩展到大型表。

    当然,我的经验是 MySQL 不经常用于会产生巨大差异的大小,但如果是的话,您还应该考虑以下几点。

    我们过去使用的一个技巧是将额外的列与插入/更新触发器结合起来,以便计算成本仅在必要时(当数据更改时)产生,而不是在每次选择。

    由于绝大多数数据库的读取频率远高于写入频率,因此这将摊销所有选择的成本。

    例如,添加一个名为 MMDD 的新列 CHAR(4) 并在其上创建索引。然后在表上设置插入/更新触发器,以便使用date 列来设置这个新触发器,基于已经提供的公式date.MONTH() || date.DAY()

    然后,在进行查询时,跳过每行函数,而是使用:

    WHERE MMDD BETWEEN '0621' AND '0921'
    

    它被索引的事实将保持速度惊人的快,在插入/更新期间触发器和额外列的成本很小。

    触发器的成本无关紧要,因为它低于每次选择操作的成本。列所需的额外存储是不利的,但是,如果您检查人们提出的所有关于数据库的问题,速度问题与存储问题的比率相当高:-)

    而且,虽然这在技术上“破坏”了 3NF,因为您复制了数据,但出于性能原因,这样做是一个由来已久的传统,如果您知道自己在做什么(即触发器减轻“损害”)。

    【讨论】:

    • 这是一个非常有用的答案,谢谢。是的,我的表包含 100,000 多行并且增长迅速,因此性能至关重要。我已经将我的一些照片、关键字和事件表合并到一个表中,以使全文索引运行更顺畅 - 所以我非常熟悉非规范化数据库。明天我会测试一下,看看效果如何,再次感谢。我希望有一天会有一个内置函数用于这个......
    【解决方案2】:

    我认为最简单的方法是获取日期,将它们转换为字符串,获取后缀,然后通过 BETWEEN 运行它:

    WHERE date.MONTH() || date.DAY() BETWEEN '0621' AND '0921'
    

    【讨论】:

    • 这可能是最简单的解决方案,所以 +1,但您应该知道它(可能还有任何 其他 解决方案)可能会严重降低您的性能。
    • 是的,我也在等待聪明的解决方案......只是想把明显的解决方案扔在那里。
    • 感谢 bdares 的解决方案,感谢 paxdiablo 的建议... 性能至关重要,我有超过 100,000 张照片并且增长速度很快。在决定应用它之前,我必须对其进行彻底测试,只是好奇我如何使用 MySQL 实际实现这一目标
    【解决方案3】:

    RIGHT 函数可能会有所帮助

    select
        current_date,
        right(current_date,5),
        right(current_date,5) between '06-21' and '09-21' `IsTodaySummer?`,
        '09-21' between '06-21' and '09-21' `Is 09-21 Summer?`;
    +--------------+-----------------------+-----------------+-------------------+
    | current_date | right(current_date,5) | IsTodaySummer? | Is 09-21 Summer? |
    +--------------+-----------------------+-----------------+-------------------+
    | 2011-09-29   | 09-29                 |               0 |                 1 |
    +--------------+-----------------------+-----------------+-------------------+
    

    但正如ajeal所说,添加另一列更好使用索引。

    【讨论】:

      【解决方案4】:

      如果你真的需要这种格式的搜索,
      我想最好把日期列分成两列,

      • year int(4) unsigned(年份)
      • month_day int(4) unsigned(即 mmdd)

      month_day, year 上构建复合索引,
      这个想法是让索引更好地工作

      查询样例

      where month_day between 621 and 921 -- make use on index
      

      另一个例子

      where year=2011 and month_day between 900 and 930 -- make use on index too
      

      【讨论】:

        【解决方案5】:

        在 MySQL 中应该有一个相当于 Oracle 的 to_date() 函数。

        【讨论】:

          【解决方案6】:

          您可以使用 monthday 函数将日期分开:

          where month(date_column) between 6 and 9
            and if(month(date_column) = 6 and day(date_column) < 21, 0, 1)
            and if(month(date_column) = 9 and day(date_column) > 21, 0, 1)
          

          if 之所以需要,是因为您的界限与月份不一致。

          如果您要做很​​多此类事情,那么您最好预先计算完整日期的月-日版本,以便您可以对其进行索引。

          【讨论】:

            【解决方案7】:

            由于您不需要年份,请从日期中减去它。 在 MySQL 中,你可以这样做:

            select * from some_table
            where date_sub(date_col, interval year(date_col) year)
            between '0000-06-21' and '0000-09-21';
            

            【讨论】:

              猜你喜欢
              • 2020-06-05
              • 2020-07-24
              • 2022-12-22
              • 1970-01-01
              • 1970-01-01
              • 2017-09-17
              • 2016-12-02
              • 1970-01-01
              • 2017-12-20
              相关资源
              最近更新 更多