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.

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().


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


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 )


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)

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


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


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)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.