Ruby on Rails: ¿cómo ordeno con dos columnas usando ActiveRecord?

91

Quiero ordenar por dos columnas, una es DateTime ( updated_at) y la otra es Decimal (Price)

Me gustaría poder ordenar primero por updated_at, luego, si ocurren varios elementos el mismo día, ordenar por Precio.

NullVoxPopuli
fuente

Respuestas:

64

Suponiendo que está usando MySQL,

Model.all(:order => 'DATE(updated_at), price')

Tenga en cuenta la distinción de las otras respuestas. La updated_atcolumna será una marca de tiempo completa, por lo que si desea ordenar en función del día en que se actualizó, debe usar una función para obtener solo la parte de la fecha de la marca de tiempo. En MySQL, eso es DATE().

Daniel Vandersluis
fuente
7
Para evitar que las uniones se rompan aleatoriamente con mensajes de "columna ambigua", debe usar la siguiente versión más sólida: :order => ["DATE(#{table_name}.updated_at)", :price](Tenga en cuenta que :pricees un símbolo).
Jo Liss
Tuve que escapar de mi columna de pedidos con algo orderasí:Model.all(:order => "day asc, `order` asc")
concesión
147

En Rails 4 puedes hacer algo similar a:

Model.order(foo: :asc, bar: :desc)

fooy barson columnas en el archivo db.

Christian Fazzini
fuente
1
Rails 4 es el mejor.
Darth Egregious
56
Thing.find(:all, :order => "updated_at desc, price asc")

hará el truco.

Actualizar:

Thing.all.order("updated_at DESC, price ASC")

es el camino a seguir de Rails 3. (Gracias @cpursley )

Erik Escobedo
fuente
4
Gracias @Erik: sé que esta respuesta es antigua, así que aquí está mi advertencia para quienes la vean ahora: este método ha quedado obsoleto al iniciar Rails 3.2. Use Thing.all en su lugar =)
Abdo
Correcta, esto funcionó bien para mí: Thing.all.order("updated_at DESC, price ASC")
cpursley
1
Su actualización fue muy útil para mí cuando necesitaba a minúsculas los valores ordenados: Thing.order("LOWER(name), number").
Nick
36

Active Record Query Interface le permite especificar tantos atributos como desee para ordenar su consulta:

models = Model.order(:date, :hour, price: :desc)

o si quieres ser más específico (gracias @ zw963 ):

models = Model.order(price: :desc, date: :desc, price: :asc) 

Bonificación: después de la primera consulta, puede encadenar otras consultas:

models = models.where('date >= :date', date: Time.current.to_date)
golfadas
fuente
Sé que esta es una publicación antigua, pero personalmente cambiaría modela modelspara que una persona sepa que está pluralizada. Sólo una sugerencia.
Tass
1
Creo que debería editar un ejemplo más especial: por ejemplo, modelos = Model.order ({price:: desc}, {date:: desc}, {price: asc})
zw963
Si alguien pegó esto y vio un error de método indefinido, hay un pequeño error tipográfico aquí. Debería ser en :asclugar de asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
nayiaw
18

En realidad, hay muchas formas de hacerlo utilizando Active Record. Uno que no se ha mencionado anteriormente sería (en varios formatos, todos válidos):

Model.order(foo: :asc).order(:bar => :desc).order(:etc)

Tal vez sea más detallado, pero personalmente me resulta más fácil de manejar. SQL se produce en un solo paso:

SELECT "models".* FROM "models" ORDER BY "models"."etc" ASC, "models"."bar" DESC, "models"."foo" ASC

Por lo tanto, para la pregunta original:

Model.order(:updated_at).order(:price)

No necesita declarar el tipo de datos, ActiveRecord lo hace sin problemas, y también lo hace su motor de base de datos

Ruby Racer
fuente
Esto funciona muy bien cuando se utilizan dos columnas de dos tablas diferentes como: Member.includes (: votante) .order ("town_club asc"). Order ("votantes.last_name asc")
bkunzi01
1
¿Corresponde el SQL que publicaste Model.order(foo: :asc).order(:bar => :desc).order(:etc)? El orden de las cláusulas de orden en SQL es el opuesto al que obtengo cuando ejecuto .to_sqleso.
Qaz
1
@Qaz esto fue hace mucho tiempo. Creo que probablemente necesite corregir este, nunca lo había notado. Lo comprobaré más tarde. Gracias.
Ruby Racer
2
Model.all(:order => 'updated_at, price')
robertokl
fuente
0

¡Ninguno de estos funcionó para mí! ¡Después de exactamente 2 días de buscar arriba y abajo en Internet, encontré una solución!

digamos que tiene muchas columnas en la tabla de productos, incluyendo: special_price y msrp. Estas son las dos columnas con las que estamos tratando de ordenar.

Bien, primero en su modelo agregue esta línea:

named_scope :sorted_by_special_price_asc_msrp_asc, { :order => 'special_price asc,msrp asc' }

En segundo lugar, en el Controlador de producto, agregue dónde necesita realizar la búsqueda:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Max Alexander Hanna
fuente