Estoy tratando de encontrar a todos los usuarios con una identificación superior a 200, pero tengo algunos problemas con la sintaxis específica.
User.where(:id > 200)
y
User.where("? > 200", :id)
Ambos han fallado.
¿Alguna sugerencia?
Estoy tratando de encontrar a todos los usuarios con una identificación superior a 200, pero tengo algunos problemas con la sintaxis específica.
User.where(:id > 200)
y
User.where("? > 200", :id)
Ambos han fallado.
¿Alguna sugerencia?
Respuestas:
Prueba esto
User.where("id > ?", 200)
?
, en lugar de incluir el 200
?
Solo he probado esto en Rails 4, pero hay una forma interesante de usar un rango con un where
hash para obtener este comportamiento.
User.where(id: 201..Float::INFINITY)
generará el SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
Lo mismo se puede hacer por menos que con -Float::INFINITY
.
Acabo de publicar una pregunta similar sobre cómo hacer esto con fechas aquí en SO .
>=
vs >
Para evitar que las personas tengan que profundizar y seguir la conversación de comentarios, aquí están los aspectos más destacados.
El método anterior solo genera una >=
consulta y no a >
. Hay muchas formas de manejar esta alternativa.
Para números discretos
Puede utilizar una number_you_want + 1
estrategia como la anterior en la que estoy interesado en Usuarios con los que id > 200
realmente busco id >= 201
. Esto está bien para números enteros y números donde puede incrementar en una sola unidad de interés.
Si tiene el número extraído en una constante bien nombrada, este puede ser el más fácil de leer y comprender de un vistazo.
Lógica invertida
Podemos usar el hecho de que x > y == !(x <= y)
y usar la cadena where not.
User.where.not(id: -Float::INFINITY..200)
que genera el SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
Esto toma un segundo extra para leer y razonar, pero funcionará para valores no discretos o columnas donde no puede usar el + 1
estrategia.
Mesa Arel
Si quieres ponerte elegante, puedes usar el Arel::Table
.
User.where(User.arel_table[:id].gt(200))
generará el SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Los detalles son los siguientes:
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`
Este enfoque le dará el SQL exacto que le interesa, sin embargo, no muchas personas usan la tabla Arel directamente y pueden encontrarla desordenada y / o confusa. Usted y su equipo sabrán qué es lo mejor para usted.
¡A partir de Rails 5 también puedes hacerlo con las fechas!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
generará el SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Una vez que se lance Ruby 2.6 (25 de diciembre de 2018), ¡podrá usar la nueva sintaxis de rango infinito! En lugar de 201..Float::INFINITY
solo podrás escribir 201..
. Más información en esta publicación de blog .
where
comparadores básicos . Pues >
sugiero usar un >= (number_you_want + 1)
para simplificar. Si realmente quiere asegurarse de que es solo una >
consulta, puede acceder a la tabla ARel. Cada clase que hereda ActiveRecord
tiene un arel_table
método getter que devuelve el Arel::Table
para esa clase. Se accede a las columnas de la tabla con el []
método like User.arel_table[:id]
. Esto devuelve un Arel::Attributes::Attribute
que puede llamar gt
y pasar 200
. Esto se puede pasar a where
. por ej 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>)
(se omiten los ticks posteriores alrededor de los nombres de tabla y columna para el formato de comentario SO).
Si desea una escritura más intuitiva, existe una gema llamada Squeel que le permitirá escribir sus instrucciones de esta manera:
User.where{id > 200}
Observe que los caracteres de 'llave' {} id
son solo un texto.
Todo lo que tienes que hacer es agregar chirrido a tu Gemfile:
gem "squeel"
Esto podría facilitarle la vida al escribir sentencias SQL complejas en Ruby.
Otra posibilidad elegante es ...
User.where("id > :id", id: 100)
Esta característica le permite crear consultas más comprensibles si desea reemplazar en varios lugares, por ejemplo ...
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Esto tiene más significado que tener mucho ?
en la consulta ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
A menudo tengo este problema con los campos de fecha (donde los operadores de comparación son muy comunes).
Para dar más detalles sobre la respuesta de Mihai, que creo que es un enfoque sólido.
A los modelos puede agregar ámbitos como este:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... y luego en su controlador, o donde sea que esté usando su modelo:
result = MyModel.updated_at_less_than('01/01/2017')
... un ejemplo más complejo con combinaciones se ve así:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
Una gran ventaja de este enfoque es que (a) le permite componer sus consultas desde diferentes ámbitos y (b) evita las colisiones de alias cuando se une a la misma tabla dos veces, ya que arel_table manejará esa parte de la generación de consultas.
Rails 6.1 agregó una nueva 'sintaxis' para operadores de comparación en where
condiciones, por ejemplo:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
Entonces su consulta puede reescribirse de la siguiente manera:
User.where('id >': 200)
Aquí hay un enlace a relaciones públicas donde puede encontrar más ejemplos.
Corta:
User.where("id > 200")
where("id > ?", 200)
sintaxis). Esto no logra eso.