Ruby on Rails: jak sortować według dwóch kolumn przy użyciu ActiveRecord?


94

Chcę sortować według dwóch kolumn, jedna to DateTime ( updated_at), a druga to Decimal (Price)

Chciałbym móc najpierw sortować według updated_at, a następnie, jeśli kilka pozycji występuje tego samego dnia, sortować według ceny.

Odpowiedzi:


66

Zakładając, że używasz MySQL,

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

Zwróć uwagę na różnicę w stosunku do innych odpowiedzi. updated_atKolumna będzie pełny znacznik czasu, więc jeśli chcesz porządek oparty na dzień została aktualizowana, trzeba użyć funkcji aby uzyskać tylko data część z datownik. To znaczy w MySQL DATE().


7
Aby zatrzymać łączy z losowo zerwania z komunikatów „niejednoznaczne” kolumn, należy użyć następującego solidniejsze wersję: :order => ["DATE(#{table_name}.updated_at)", :price](zauważ, że :pricejest symbolem.)
Jo Liss

Musiałem uciec od kolumny z zamówieniami w ten ordersposób:Model.all(:order => "day asc, `order` asc")
grant


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

da rade.

Aktualizacja:

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

jest droga Rails 3. (Dzięki @cpursley )


4
Dziękuję @Erik - wiem, że ta odpowiedź jest stara, więc oto moje ostrzeżenie dla tych, którzy ją teraz widzą: Ta metoda została wycofana z Railsów 3.2. Zamiast tego użyj Thing.all =)
Abdo

Prawidłowo, to działało dobrze dla mnie: Thing.all.order("updated_at DESC, price ASC")
cpursley

1
Twoja zmiana było pomocne dla mnie, gdy potrzebowałem na małe posortowanych wartości: Thing.order("LOWER(name), number").
Nick

36

Interfejs kwerendy Active Record pozwala określić dowolną liczbę atrybutów w celu uporządkowania zapytania:

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

lub jeśli chcesz uzyskać bardziej szczegółowe informacje (dzięki @ zw963 ):

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

Bonus: po pierwszym zapytaniu możesz łączyć inne zapytania:

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

Wiem, że to stary post, ale osobiście zmieniłbym modelna, modelsaby ktoś wiedział, że jest w liczbie mnogiej. Tylko sugestia.
Tass

1
Myślę, że powinienem edytować bardziej konkretny przykład: np. Models = Model.order ({price:: desc}, {date:: desc}, {price: asc})
zw963

jeśli ktoś to wkleił i zobaczył niezdefiniowany błąd metody, jest tu mała literówka. Powinien być :asczamiast asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
nayiaw

18

Właściwie jest na to wiele sposobów przy użyciu modułu Active Record. Jeden, o którym nie wspomniano powyżej, to (w różnych formatach, wszystkie prawidłowe):

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

Może jest bardziej rozwlekły, ale osobiście łatwiej mi się nim zarządza. SQL jest tworzony tylko w jednym kroku:

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

Tak więc w przypadku pierwotnego pytania:

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

Nie musisz deklarować typu danych, ActiveRecord robi to płynnie, podobnie jak twój silnik DB


Działa to doskonale, kiedy za pomocą dwóch kolumn z dwóch różnych tabel, takich jak: Member.includes (: wyborców) .order ( "town_club mal") zamówienie ( "voters.last_name ASC").
bkunzi01

1
Czy opublikowany kod SQL odpowiada Model.order(foo: :asc).order(:bar => :desc).order(:etc)? Kolejność klauzul kolejności w SQL jest odwrotna do tego, co otrzymuję, gdy .to_sqlna tym uruchamiam .
Qaz,

1
@Qaz to było dawno temu. Myślę, że prawdopodobnie muszę to poprawić, nigdy nie zauważyłem. Jeszcze raz sprawdzę później. Dzięki.
Ruby Racer


0

Żaden z nich nie zadziałał dla mnie! Po dokładnie 2 dniach szukania w internecie od góry do dołu znalazłem rozwiązanie!

powiedzmy, że masz wiele kolumn w tabeli produktów, w tym: cena_specjalna i msrp. To są dwie kolumny, według których próbujemy sortować.

OK, najpierw w swoim Modelu dodaj tę linię:

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

Po drugie, w Kontrolerze produktu dodaj miejsce, w którym chcesz przeprowadzić wyszukiwanie:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.