185

IDが200を超えるすべてのユーザーを検索しようとしていますが、特定の構文に問題があります。

User.where(:id > 200) 

User.where("? > 200", :id) 

両方とも失敗しました。

助言がありますか?

4

10 に答える 10

316

これを試して

User.where("id > ?", 200) 
于 2012-07-03T19:22:13.730 に答える
175

最先端

Ruby 2.7 ではbeginless 範囲が導入され><とそれらの包括的ないとこ (>=<=) をさらに簡単に指定できるようになりました。

User.where(id: 200..).to_sql
  => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" >= 200"
# There is no difference w/ a non-inclusive endless range (e.g. `200...`)

User.where(id: ..200).to_sql
  => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" <= 200"
User.where(id: ...200).to_sql
  => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"id\" < 200"

これは、タイムスタンプでも完全に機能します!

User.where(created_at: 1.day.ago..).to_sql
  => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"created_at\" >= '2021-09-12 15:38:32.665061'"
User.where(created_at: ..1.day.ago).to_sql
  => "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"created_at\" <= '2021-09-12 15:38:37.756870'"

元の回答と更新

これは 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::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..。詳細については、このブログ投稿をご覧ください。

于 2014-05-29T14:51:36.750 に答える
24

より良い使い方は、ユーザー モデルでスコープを作成することです。where(arel_table[:id].gt(id))

于 2016-08-08T21:07:12.847 に答える
20

アップデート

Rails コア チームは、この変更についてより詳細に議論するために、しばらくの間この変更を元に戻すことにしました。詳細については、このコメントこの PRを参照してください。

教育目的でのみ回答を残しています。


Rails 6.1 での比較のための新しい「構文」 (元に戻された)

whereRails 6.1 では、条件内の比較演算子に新しい「構文」が追加されました。次に例を示します。

Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)

したがって、クエリは次のように書き直すことができます。

User.where('id >': 200) 

これはPRへのリンクで、より多くの例を見つけることができます。

于 2020-07-21T17:10:10.187 に答える
0

Ruby 2.6の場合、次のような範囲を受け入れることができます:

# => 2.6
User.where(id: 201..)
# < 2.6
User.where(id: 201..Float::INFINITY)
于 2021-03-24T13:05:09.690 に答える
-3

短い:

User.where("id > 200")
于 2017-02-09T00:48:42.500 に答える