Answers:
试试这个
User.where("id > ?", 200)
?
而不是内联200
吗?
我仅在Rails 4中对此进行了测试,但是有一种有趣的方式将范围与where
哈希一起使用来获得此行为。
User.where(id: 201..Float::INFINITY)
将生成SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
可以用少于做相同的事情-Float::INFINITY
。
我刚刚在SO上发布了一个类似的问题,询问是否要使用日期。
>=
与 >
为避免人们不得不深入研究和关注评论对话,这里是重点。
上面的方法仅生成>=
查询,而不生成>
。有很多方法可以处理此替代方案。
对于离散数
您可以使用上述number_you_want + 1
策略,让我对“用户”感兴趣,id > 200
但实际上却在寻找id >= 201
。这对于整数和数字都可以,您可以按一个感兴趣的单位递增。
如果您将数字提取到一个命名良好的常量中,则一目了然可能是最容易阅读和理解的。
倒逻辑
我们可以使用事实,x > y == !(x <= y)
并使用where not链。
User.where.not(id: -Float::INFINITY..200)
生成SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
这需要花额外的一秒钟时间来阅读并进行推理,但适用于不能使用 + 1
策略的。
Arel表
如果想花哨的话,可以利用Arel::Table
。
User.where(User.arel_table[:id].gt(200))
将生成SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
具体如下:
User.arel_table #=> an Arel::Table instance for the User model / users table
User.arel_table[:id] #=> an Arel::Attributes::Attribute for the id column
User.arel_table[:id].gt(200) #=> an Arel::Nodes::GreaterThan which can be passed to `where`
这种方法将为您提供您感兴趣的确切 SQL,但是没有多少人直接使用Arel表,并且会发现它凌乱和/或令人困惑。您和您的团队将知道最适合您的。
从Rails 5开始,您还可以添加日期!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
将生成SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Ruby 2.6发布后(2018年12月25日),您将可以使用新的无限范围语法!取而代之的是201..Float::INFINITY
你只能写东西201..
。更多信息,请参阅此博客文章。
where
匹配器来做到这一点。为了简单起见,>
我建议使用a >= (number_you_want + 1)
。如果您真的想确保它只是一个>
查询,则可以访问ARel表。每个继承自的类ActiveRecord
都有一个arel_table
getter方法,该方法返回Arel::Table
该类的。表格中的列可使用[]
方式访问User.arel_table[:id]
。这将返回一个Arel::Attributes::Attribute
您可以调用gt
并传递的信息200
。然后可以将其传递给where
。例如User.where(User.arel_table[:id].gt(200))
。
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
。
WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(对于SO注释格式,省略了表和列名的反斜线)。
如果您想要更直观的写作,可以使用名为squeel的gem 来编写如下指令:
User.where{id > 200}
请注意,“括号”字符{} id
只是文本。
您要做的就是将squeel添加到您的Gemfile中:
gem "squeel"
在Ruby中编写复杂的SQL语句时,这可能会大大减轻您的生活。
我经常在日期字段(比较运算符很常见)中遇到这个问题。
为了进一步阐述Mihai的答案,我认为这是一个可靠的方法。
您可以向模型添加如下范围:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
...然后在您的控制器中,或者在您使用模型的任何地方:
result = MyModel.updated_at_less_than('01/01/2017')
...带有连接的更复杂的示例如下所示:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
这种方法的一个巨大优势是(a)它允许您从不同的范围组合查询,并且(b)当您两次连接到同一表时避免别名冲突,因为arel_table将处理查询生成的那部分。