【问题标题】:How do I write an activerecord query that only looks at the time component of a datetime field?如何编写仅查看日期时间字段的时间组件的 activerecord 查询?
【发布时间】:2011-10-12 07:02:36
【问题描述】:

是否可以进行仅查看日期时间字段的时间部分的 activerecord 查询?

例如Battle.where('start_time < ? and start_time > ?','12:00','06:00')

要查找在早上 6 点到下午 12 点之间开始的所有战斗,无论它们发生在哪一天?在本例中,start_time 定义为日期时间。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 datetime activerecord time


    【解决方案1】:

    这样做的唯一方法是使用 SQL 函数,如果你在 MySQL 上,你可以这样做:

    Battle.where( 'HOUR( start_time ) >= ? AND HOUR( start_time ) <= ?', 12, 6 )
    

    但这非常低效,并且总是会生成全表扫描,而您肯定不希望这样。

    最好的解决方案是在你的战斗模型中单独添加带有小时值的列,索引它们并直接查询它们,如下所示:

    Battle.where( 'start_time_hour >= ? start_time_hour <= ?', 12, 6 )
    

    只需添加一个 before_save 回调来设置此值,然后再根据 start_time 属性保存您的战斗模型。

    编辑

    顺便说一句,如果您使用的是 PostgreSQL,它能够为函数的结果创建索引,因此,如果您不介意必须坚持使用 PostgreSQL,您可以只使用 SQL 函数。在你问之前,不,我不知道它是如何工作的,我只知道数据库允许你这样做,而这在 MySQL 上是不可用的。

    【讨论】:

    • 太棒了,谢谢。在开发中,我在 SQLite 中使用了 Battle.where('time(start_time) ?', '12', '6') 似乎有效。我计划在生产中使用 PostgreSQL,以便可以使用您的代码。我注意到的唯一问题是这似乎忽略了我的时区(我们绕过 Rails 并不奇怪)。我已经开始考虑这个问题了,但它让我很头疼,所以我稍后再讨论。使用预先转换的时区设置小时列可能是最简单的方法。
    猜你喜欢
    • 2019-08-18
    • 1970-01-01
    • 2018-05-31
    • 2012-11-15
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多