IDが200を超えるすべてのユーザーを検索しようとしていますが、特定の構文に問題があります。
User.where(:id > 200)
と
User.where("? > 200", :id)
両方とも失敗しました。
助言がありますか?
IDが200を超えるすべてのユーザーを検索しようとしていますが、特定の構文に問題があります。
User.where(:id > 200)
と
User.where("? > 200", :id)
両方とも失敗しました。
助言がありますか?
これを試して
User.where("id > ?", 200)
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..
。詳細については、このブログ投稿をご覧ください。
より良い使い方は、ユーザー モデルでスコープを作成することです。where(arel_table[:id].gt(id))
Rails コア チームは、この変更についてより詳細に議論するために、しばらくの間この変更を元に戻すことにしました。詳細については、このコメントとこの PRを参照してください。
教育目的でのみ回答を残しています。
where
Rails 6.1 では、条件内の比較演算子に新しい「構文」が追加されました。次に例を示します。
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
したがって、クエリは次のように書き直すことができます。
User.where('id >': 200)
これはPRへのリンクで、より多くの例を見つけることができます。
Ruby 2.6の場合、次のような範囲を受け入れることができます:
# => 2.6
User.where(id: 201..)
# < 2.6
User.where(id: 201..Float::INFINITY)
短い:
User.where("id > 200")