Ruby on Rails: Wie sortiere ich mit ActiveRecord mit zwei Spalten?


90

Ich möchte nach zwei Spalten sortieren, eine ist eine DateTime ( updated_at) und die andere ist eine Dezimalzahl (Price).

Ich möchte in der Lage sein, zuerst nach update_at zu sortieren und dann, wenn mehrere Artikel am selben Tag auftreten, nach Preis zu sortieren.

Antworten:


64

Angenommen, Sie verwenden MySQL.

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

Beachten Sie den Unterschied zu den anderen Antworten. Die updated_atSpalte ist ein vollständiger Zeitstempel. Wenn Sie also nach dem Tag der Aktualisierung sortieren möchten , müssen Sie eine Funktion verwenden, um nur den Datumsteil aus dem Zeitstempel abzurufen. In MySQL also DATE().


7
Um zu verhindern, dass Joins zufällig mit "mehrdeutigen Spalten" -Nachrichten unterbrochen werden, sollten Sie die folgende robustere Version verwenden: :order => ["DATE(#{table_name}.updated_at)", :price](Beachten Sie, dass dies :priceein Symbol ist.)
Jo Liss

Ich musste meiner Bestellspalte folgendermaßen entkommen order:Model.all(:order => "day asc, `order` asc")
Gewähren Sie


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

wird den Trick machen.

Aktualisieren:

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

ist der Rails 3 Weg zu gehen. (Vielen Dank @cpursley )


4
Vielen Dank @Erik - Ich weiß, dass diese Antwort alt ist. Hier ist meine Warnung für diejenigen, die sie jetzt sehen: Diese Methode ist ab Rails 3.2 veraltet. Verwenden Sie stattdessen Thing.all =)
Abdo

Richtig, das hat bei mir gut funktioniert: Thing.all.order("updated_at DESC, price ASC")
cpursley

1
Ihr Update war hilfreich für mich, als ich die sortierten Werte in Kleinbuchstaben schreiben musste : Thing.order("LOWER(name), number").
Nick

34

Mit der Active Record Query Interface können Sie so viele Attribute angeben, wie Sie für Ihre Abfrage bestellen möchten :

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

oder wenn Sie genauer werden möchten (danke @ zw963 ):

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

Bonus: Nach der ersten Abfrage können Sie andere Abfragen verketten:

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

Ich weiß, dass dies ein alter Beitrag ist, aber ich würde persönlich zu wechseln model, modelsdamit eine Person weiß, dass er pluralisiert ist. Nur ein Vorschlag.
Tass

1
Ich denke, ich sollte ein spezielleres Beispiel bearbeiten: zB models = Model.order ({price :: desc}, {date :: desc}, {price: asc})
zw963

Wenn jemand dies eingefügt hat und einen undefinierten Methodenfehler festgestellt hat, gibt es hier einen kleinen Tippfehler. Es sollte :ascstatt sein asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
Nayiaw

18

Tatsächlich gibt es viele Möglichkeiten, dies mit Active Record zu tun. Eine, die oben nicht erwähnt wurde, wäre (in verschiedenen Formaten, alle gültig):

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

Vielleicht ist es ausführlicher, aber ich persönlich finde es einfacher zu verwalten. SQL wird nur in einem Schritt erstellt:

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

Also für die ursprüngliche Frage:

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

Sie müssen den Datentyp nicht deklarieren. ActiveRecord erledigt dies reibungslos, ebenso wie Ihre DB Engine


Dies funktioniert hervorragend, wenn zwei Spalten aus zwei verschiedenen Tabellen verwendet werden, z. B.: Member.includes (: voter) .order ("town_club asc"). Order ("Voter.last_name asc")
bkunzi01

1
Entspricht das von Ihnen veröffentlichte SQL Model.order(foo: :asc).order(:bar => :desc).order(:etc)? Die Reihenfolge der order-Klauseln in SQL ist das Gegenteil von dem, was ich bekomme, wenn ich darauf laufe .to_sql.
Qaz

1
@ Qaz das ist lange her. Ich denke, ich muss das wahrscheinlich korrigieren, ich hatte es nie bemerkt. Ich werde es später noch einmal überprüfen. Vielen Dank.
Ruby Racer


0

Nichts davon hat bei mir funktioniert! Nachdem ich genau 2 Tage lang über das Internet nach oben und unten geschaut hatte, fand ich eine Lösung !!

Angenommen, die Produkttabelle enthält viele Spalten, darunter: special_price und msrp. Dies sind die beiden Spalten, mit denen wir sortieren möchten.

Okay, fügen Sie zuerst in Ihrem Modell diese Zeile hinzu:

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

Zweitens fügen Sie im Product Controller hinzu, wo Sie die Suche durchführen müssen:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.