一尘不染

Rails`where`的时间少于查询时间

sql

设置

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,但是如果可以用字符串以外的对象来完成,那么我想这样做。

电位(兆)答案

这有点糟糕,但是可以使用Time.at(0)和进行范围调整Time.at(Float::MAX)。我有一种感觉,尽管它们可能导致同样糟糕的SQL查询。


阅读 217

收藏
2021-03-17

共1个答案

一尘不染

编辑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').

原始(Rails <5)答案

似乎没有一种方法可以使用基本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)
2021-03-17