Ich versuche, alle Benutzer mit einer ID größer als 200 zu finden, habe jedoch Probleme mit der spezifischen Syntax.
User.where(:id > 200)
und
User.where("? > 200", :id)
haben beide versagt.
Irgendwelche Vorschläge?
Ich versuche, alle Benutzer mit einer ID größer als 200 zu finden, habe jedoch Probleme mit der spezifischen Syntax.
User.where(:id > 200)
und
User.where("? > 200", :id)
haben beide versagt.
Irgendwelche Vorschläge?
Antworten:
Versuche dies
User.where("id > ?", 200)
?
, anstatt die zu inlinieren 200
?
Ich habe dies nur in Rails 4 getestet, aber es gibt eine interessante Möglichkeit, einen Bereich mit einem where
Hash zu verwenden, um dieses Verhalten zu erhalten.
User.where(id: 201..Float::INFINITY)
generiert die SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
Das gleiche kann für weniger als mit gemacht werden -Float::INFINITY
.
Ich habe gerade eine ähnliche Frage mit Daten hier auf SO gestellt .
>=
vs. >
Um zu vermeiden, dass die Leute die Kommentare durchgehen und den Kommentaren folgen müssen, sind hier die Highlights.
Die oben beschriebene Methode nur erzeugt eine >=
Abfrage und nicht ein >
. Es gibt viele Möglichkeiten, mit dieser Alternative umzugehen.
Für diskrete Zahlen
Sie können eine number_you_want + 1
Strategie wie oben verwenden, bei der ich an Benutzern interessiert bin, die id > 200
aber tatsächlich suchen id >= 201
. Dies ist in Ordnung für Ganzzahlen und Zahlen, bei denen Sie um eine einzelne interessierende Einheit erhöhen können.
Wenn Sie die Zahl in eine gut benannte Konstante extrahieren lassen, ist dies möglicherweise auf einen Blick am einfachsten zu lesen und zu verstehen.
Invertierte Logik
Wir können die Tatsache nutzen, dass x > y == !(x <= y)
und die wo nicht Kette verwenden.
User.where.not(id: -Float::INFINITY..200)
das generiert die SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
Das Lesen und Begründen dauert eine zusätzliche Sekunde, funktioniert jedoch für nicht diskrete Werte oder Spalten, bei denen Sie die + 1
Strategie nicht verwenden können .
Arel Tisch
Wenn Sie Lust haben, können Sie die nutzen Arel::Table
.
User.where(User.arel_table[:id].gt(200))
generiert die SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Die Einzelheiten sind wie folgt:
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`
Mit diesem Ansatz erhalten Sie genau das SQL, an dem Sie interessiert sind. Allerdings verwenden nicht viele Benutzer die Arel-Tabelle direkt und können sie als unübersichtlich und / oder verwirrend empfinden. Sie und Ihr Team wissen, was für Sie am besten ist.
Ab Rails 5 können Sie dies auch mit Daten tun!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
generiert die SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Sobald Ruby 2.6 veröffentlicht ist (25. Dezember 2018), können Sie die neue Syntax für unendliche Bereiche verwenden! Stattdessen können 201..Float::INFINITY
Sie einfach schreiben 201..
. Weitere Infos in diesem Blogbeitrag .
where
Matchern tun können . Denn >
ich schlage vor, der >= (number_you_want + 1)
Einfachheit halber ein zu verwenden. Wenn Sie wirklich sicherstellen möchten, dass es sich nur um eine >
Abfrage handelt, können Sie auf die ARel-Tabelle zugreifen. Jede Klasse, die von erbt, ActiveRecord
verfügt über eine arel_table
Getter-Methode, die die Arel::Table
für diese Klasse zurückgibt . Auf Spalten in der Tabelle wird mit der []
Methode like zugegriffen User.arel_table[:id]
. Dies gibt eine zurück, die Arel::Attributes::Attribute
Sie anrufen gt
und weitergeben können 200
. Dies kann dann an übergeben werden where
. zB 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>)
(Back Ticks um Tabellen- und Spaltennamen, die für die SO-Kommentarformatierung weggelassen wurden).
Wenn Sie intuitiver schreiben möchten, gibt es einen Edelstein namens Squeel , mit dem Sie Ihre Anweisungen wie folgt schreiben können:
User.where{id > 200}
Beachten Sie, dass die 'Klammer'-Zeichen {} id
nur ein Text sind.
Alles, was Sie tun müssen, ist, Ihrem Gemfile Squeel hinzuzufügen:
gem "squeel"
Dies kann Ihr Leben beim Schreiben komplexer SQL-Anweisungen in Ruby erheblich erleichtern.
Eine andere ausgefallene Möglichkeit ist ...
User.where("id > :id", id: 100)
Mit dieser Funktion können Sie verständlichere Abfragen erstellen, wenn Sie diese an mehreren Stellen ersetzen möchten, z.
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Dies hat mehr Bedeutung als viel ?
auf der Abfrage zu haben ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
Ich habe oft dieses Problem mit Datumsfeldern (wo Vergleichsoperatoren sehr häufig sind).
Die Antwort von Mihai näher zu erläutern, die ich für einen soliden Ansatz halte.
Zu den Modellen können Sie folgende Bereiche hinzufügen:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... und dann in Ihrem Controller oder wo immer Sie Ihr Modell verwenden:
result = MyModel.updated_at_less_than('01/01/2017')
... ein komplexeres Beispiel mit Joins sieht folgendermaßen aus:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
Ein großer Vorteil dieses Ansatzes besteht darin, dass (a) Sie Ihre Abfragen aus verschiedenen Bereichen zusammenstellen können und (b) Alias-Kollisionen vermieden werden, wenn Sie zweimal derselben Tabelle beitreten, da arel_table diesen Teil der Abfragegenerierung verarbeitet.
Rails 6.1 hat eine neue 'Syntax' für Vergleichsoperatoren unter where
Bedingungen hinzugefügt , zum Beispiel:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
So kann Ihre Anfrage wie folgt umgeschrieben werden:
User.where('id >': 200)
Hier ist ein Link zu PR, wo Sie weitere Beispiele finden.
Kürzere:
User.where("id > 200")
where("id > ?", 200)
Syntax) vermeiden möchte . Das erreicht das nicht.