Ruby on Rails: come posso ordinare con due colonne usando ActiveRecord?


91

Voglio ordinare per due colonne, una è DateTime ( updated_at) e l'altra è un Decimal (Price)

Vorrei essere in grado di ordinare prima per updated_at, quindi, se più elementi si verificano nello stesso giorno, ordinare per Prezzo.

Risposte:


64

Supponendo che tu stia utilizzando MySQL,

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

Notare la distinzione dalle altre risposte. La updated_atcolonna sarà un timestamp completo, quindi se desideri ordinare in base al giorno in cui è stato aggiornato, devi utilizzare una funzione per ottenere solo la parte della data dal timestamp. In MySQL, questo è DATE().


7
Per evitare che i join si interrompano casualmente con messaggi di "colonna ambigua", dovresti utilizzare la seguente versione più robusta: :order => ["DATE(#{table_name}.updated_at)", :price](Nota che :priceè un simbolo.)
Jo Liss

Ho dovuto uscire dalla mia colonna degli ordini ordercosì:Model.all(:order => "day asc, `order` asc")
concedi


56
Thing.find(:all, :order => "updated_at desc, price asc")

farà il trucco.

Aggiornare:

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

è la strada giusta per Rails 3. (Grazie @cpursley )


4
Grazie @Erik - So che questa risposta è vecchia, quindi ecco il mio avvertimento per coloro che la vedono ora: questo metodo è stato deprecato a partire da Rails 3.2. Usa Thing.all invece =)
Abdo

Esatto, questo ha funzionato bene per me: Thing.all.order("updated_at DESC, price ASC")
cpursley

1
Il tuo aggiornamento è stato utile per me quando avevo bisogno di minuscole i valori ordinati: Thing.order("LOWER(name), number").
Nick

36

L'interfaccia Active Record Query ti consente di specificare tutti gli attributi che desideri per ordinare la query:

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

o se vuoi essere più specifico (grazie @ zw963 ):

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

Bonus: dopo la prima query, puoi concatenare altre query:

models = models.where('date >= :date', date: Time.current.to_date)

So che questo è un vecchio post, ma lo cambierei personalmente modelin modelsmodo che una persona sappia che è pluralizzato. Solo un suggerimento.
Tass

1
Penso che dovrebbe modificare un esempio più specifico: ad esempio models = Model.order ({price:: desc}, {date:: desc}, {price: asc})
zw963

se qualcuno ha incollato questo e ha visto un errore di metodo non definito, c'è un piccolo errore di battitura qui. Dovrebbe essere :ascinvece di asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
nayiaw

18

In realtà ci sono molti modi per farlo usando Active Record. Uno che non è stato menzionato sopra sarebbe (in vari formati, tutti validi):

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

Forse è più prolisso, ma personalmente lo trovo più facile da gestire. SQL viene prodotto in un solo passaggio:

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

Pertanto, per la domanda originale:

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

Non è necessario dichiarare il tipo di dati, ActiveRecord lo fa senza problemi, così come il tuo motore di database


Funziona alla grande quando si utilizzano due colonne da due tabelle diverse come: Member.includes (: voter) .order ("town_club asc"). Order ("voters.last_name asc")
bkunzi01

1
L'SQL che hai postato corrisponde Model.order(foo: :asc).order(:bar => :desc).order(:etc)? L'ordine delle clausole di ordine nell'SQL è l'opposto di quello che ottengo quando corro .to_sqlsu quello.
Qaz

1
@Qaz questo è molto tempo fa. Penso che probabilmente avrei bisogno di correggere questo, non l'avevo mai notato. Controllerò due volte più tardi. Grazie.
Ruby Racer


0

Nessuno di questi ha funzionato per me! Dopo esattamente 2 giorni passati a guardare dall'alto in basso su Internet, ho trovato una soluzione !!

diciamo che hai molte colonne nella tabella dei prodotti, tra cui: special_price e msrp. Queste sono le due colonne con cui stiamo cercando di ordinare.

Ok, prima nel tuo modello aggiungi questa riga:

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

In secondo luogo, nel Product Controller, aggiungi dove devi eseguire la ricerca:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.