ruby-on-rails Rails `where`用于时间小于查询

carvr3hs  于 2023-03-24  发布在  Ruby
关注(0)|答案(5)|浏览(168)

设置

Rails的where方法可以接受一个散列中的范围来生成一个查询,该查询将搜索该范围内的值。例如:

User.where(cash_money: 10..1000)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`cash_money` BETWEEN 10 AND 1000)

这也可以与时间戳一起使用,如

User.where(last_deposit: 10.days.ago..1000.days.ago)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` BETWEEN '2014-05-19 14:42:36' AND '2011-09-02 14:42:36')

我发现,可以使用像这样的哈希语法对数字执行简单的小于或大于操作

User.where(cash_money: 10..Float::INFINITY)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`cash_money` >= 10)

并且对于小于查询,可以用-Float::INFINITY完成相同的操作。

问题

有没有一种方法可以用时间戳来做这件事,这样我就可以得到一个像下面这样的查询?

SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` >= '2014-05-19 14:42:36')

我不能使用Float::INFINITYDate::Infinity与范围,因为它们都与ArgumentError: bad value for range错误。

当前简单方案

User.where('`users`.`last_deposit` >= ?', 10.days.ago)

将生成相同的SQL,但如果这可以用字符串以外的对象完成,我想这样做。

潜在(Meh)答案

这有点糟糕,但可以使用Time.at(0)Time.at(Float::MAX)的范围来完成。我有一种感觉,这些可能会导致同样糟糕的SQL查询。

nzk0hqpo

nzk0hqpo1#

编辑2 5/9/20

如果你使用的是Ruby 2.6,你可以使用无限的范围,而在Ruby 2.7中,你可以使用无开始的范围。
例如:

# Ruby >= 2.6
User.where(last_deposit: 10.days.ago..)

生成

SELECT "users".* FROM "users" WHERE "user"."last_deposit" >= '2020-04-29 21:58:39.109419'"

以及

# Ruby >= 2.7
User.where(last_deposit: ..10.days.ago)

生成

SELECT "users".* FROM "users" WHERE "users"."last_deposit" <= '2020-04-29 22:01:05.582055'

编辑

这在Rails 5中是可能的!

User.where(last_deposit: 10.days.ago..DateTime::Infinity.new)

将生成SQL

SELECT `users`.* FROM `users` WHERE (`users`.`last_deposit` >= '2018-06-30 17:08:54.130085').

Original(and Rails〈5)Answer

似乎没有一种方法可以使用基本的where哈希语法来生成一个大于或小于时间戳的查询。最简单和最可读的方法在我的问题Current Simple Solution中概述。
另一种方法是使用ARel,但你必须进行一些不太常见的调用。首先,你可以获得AR类的ARel表的句柄,访问列,将大于gt,大于或等于gteq,小于lt和/或小于或等于lteq方法的结果与参数传递给where
在上述情况下,这将像这样完成:

last_deposit_column = User.arel_table[:last_deposit]
last_deposit_over_ten_days_ago = last_deposit_column.gteq(10.days.ago)
User.where(last_deposit_over_ten_days_ago)
mctunoxg

mctunoxg2#

你试过这个吗?:

User.where(last_deposit: Time.at(0)...10.days.ago)

SQL语句:

SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` >= '1970-01-01 00:00:00' AND `users`.`last_deposit` < '2015-01-10 17:15:19')
3lxsmp7m

3lxsmp7m3#

你需要使用合适的无穷大。时间戳是DateTime而不是Date。使用DateTime::Infinity.new代替,或者使用DateTime::Infinity.new(-1)表示负无穷大。
相关:Is there a way to express 'Infinite Time' in Ruby?

insrf1ej

insrf1ej4#

Rails 5(和Ruby〈2.7)
User.where(last_deposit: 10.days.ago.to_datetime..DateTime::Infinity.new)
这也应该起作用:User.where(last_deposit: 10.days.ago..DateTime::Infinity.new)
但在某个日期之前有问题的范围:
User.where(last_deposit: DateTime::Infinity.new..10.days.ago.to_datetime)
DateTime::Infinity.new现在等于Float::INFINITY。Time.current(所以3.minutes.ago也是)不支持Float的范围。
将其转换为日期时间可以解决这个问题

fjaof16o

fjaof16o5#

试试这个:

User.where(last_deposit.gt(10.days.ago))

相关问题