Saya mencoba menemukan semua Pengguna dengan id lebih dari 200, tetapi saya mengalami beberapa masalah dengan sintaksis tertentu.
User.where(:id > 200)
dan
User.where("? > 200", :id)
keduanya gagal.
Ada saran?
Saya mencoba menemukan semua Pengguna dengan id lebih dari 200, tetapi saya mengalami beberapa masalah dengan sintaksis tertentu.
User.where(:id > 200)
dan
User.where("? > 200", :id)
keduanya gagal.
Ada saran?
Jawaban:
Coba ini
User.where("id > ?", 200)
?
, daripada memasukkan 200
?
Saya hanya menguji ini di Rails 4 tetapi ada cara yang menarik untuk menggunakan rentang dengan where
hash untuk mendapatkan perilaku ini.
User.where(id: 201..Float::INFINITY)
akan menghasilkan SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
Hal yang sama dapat dilakukan dengan kurang dari dengan -Float::INFINITY
.
Saya baru saja memposting pertanyaan serupa bertanya tentang melakukan ini dengan tanggal di SO .
>=
vs. >
Untuk menghindari orang harus menggali dan mengikuti percakapan komentar di sini adalah yang utama.
Metode di atas hanya menghasilkan >=
kueri dan bukan a >
. Ada banyak cara untuk menangani alternatif ini.
Untuk angka diskrit
Anda dapat menggunakan number_you_want + 1
strategi seperti di atas di mana saya tertarik dengan Pengguna id > 200
tetapi sebenarnya mencari id >= 201
. Ini bagus untuk bilangan bulat dan angka di mana Anda dapat menambah dengan satu unit bunga.
Jika Anda memiliki nomor yang diekstraksi ke dalam konstanta yang dinamai dengan baik, ini mungkin yang paling mudah untuk dibaca dan dipahami sekilas.
Logika terbalik
Kita bisa menggunakan fakta itu x > y == !(x <= y)
dan menggunakan rantai di mana tidak.
User.where.not(id: -Float::INFINITY..200)
yang menghasilkan SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
Ini membutuhkan beberapa detik tambahan untuk membaca dan alasan tentang tetapi akan bekerja untuk nilai atau kolom non diskrit di mana Anda tidak dapat menggunakan + 1
strategi.
Meja Arel
Jika Anda ingin menjadi mewah, Anda dapat menggunakan Arel::Table
.
User.where(User.arel_table[:id].gt(200))
akan menghasilkan SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Spesifikasinya adalah sebagai berikut:
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`
Pendekatan ini akan memberi Anda SQL yang tepat yang Anda minati, tetapi tidak banyak orang yang menggunakan tabel Arel secara langsung dan dapat menemukannya berantakan dan / atau membingungkan. Anda dan tim Anda akan tahu apa yang terbaik untuk Anda.
Mulai di Rails 5 Anda juga dapat melakukan ini dengan tanggal!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
akan menghasilkan SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Setelah Ruby 2.6 dirilis (25 Desember 2018), Anda dapat menggunakan sintaks rentang tak terbatas baru! Alih-alih, 201..Float::INFINITY
Anda hanya bisa menulis 201..
. Info lebih lanjut di posting blog ini .
where
pencocokan dasar . Karena >
saya sarankan menggunakan >= (number_you_want + 1)
untuk kesederhanaan. Jika Anda benar-benar ingin memastikan itu hanya >
kueri, Anda dapat mengakses tabel ARel. Setiap kelas yang mewarisi dari ActiveRecord
memiliki arel_table
metode pengambil yang mengembalikan Arel::Table
untuk kelas itu. Kolom pada tabel diakses dengan []
metode seperti User.arel_table[:id]
. Ini mengembalikan Arel::Attributes::Attribute
Anda dapat memanggil gt
dan masuk 200
. Ini kemudian dapat diteruskan ke where
. mis 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>)
(kutu belakang di sekitar nama tabel dan kolom dihilangkan untuk pemformatan komentar SO).
Jika Anda ingin tulisan yang lebih intuitif, ada permata yang disebut squeel yang memungkinkan Anda menulis instruksi seperti ini:
User.where{id > 200}
Perhatikan karakter 'penjepit' {} dan id
hanya berupa teks.
Yang harus Anda lakukan adalah menambahkan squeel ke Gemfile Anda:
gem "squeel"
Ini mungkin memudahkan hidup Anda saat menulis pernyataan SQL yang kompleks di Ruby.
Kemungkinan mewah lainnya adalah ...
User.where("id > :id", id: 100)
Fitur ini memungkinkan Anda untuk membuat kueri yang lebih komprehensif jika Anda ingin mengganti di banyak tempat, misalnya ...
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Ini memiliki arti lebih daripada memiliki banyak ?
pada permintaan ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
Saya sering mengalami masalah ini dengan bidang tanggal (di mana operator pembanding sangat umum).
Untuk menjelaskan lebih lanjut tentang jawaban Mihai, yang saya percaya merupakan pendekatan yang solid.
Untuk model, Anda dapat menambahkan cakupan seperti ini:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... dan kemudian di controller Anda, atau di mana pun Anda menggunakan model Anda:
result = MyModel.updated_at_less_than('01/01/2017')
... contoh yang lebih kompleks dengan gabungan terlihat seperti ini:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
Keuntungan yang sangat besar dari pendekatan ini adalah (a) memungkinkan Anda menyusun pertanyaan Anda dari lingkup yang berbeda dan (b) menghindari collision alias ketika Anda bergabung ke tabel yang sama dua kali karena arel_table akan menangani bagian dari generasi permintaan tersebut.
Rails 6.1 menambahkan 'sintaks' baru untuk operator perbandingan dalam where
kondisi, misalnya:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
Jadi permintaan Anda dapat ditulis ulang sebagai berikut:
User.where('id >': 200)
Berikut ini tautan ke PR tempat Anda dapat menemukan lebih banyak contoh.
Singkat:
User.where("id > 200")
where("id > ?", 200)
sintaks). Ini tidak mencapai itu.