Ruby on Rails: как сортировать по двум столбцам с помощью ActiveRecord?

94

Я хочу отсортировать по двум столбцам: один - DateTime ( updated_at), а другой - десятичный (цена)

Я хотел бы иметь возможность сначала сортировать по updated_at, а затем, если в один день появляется несколько элементов, сортировать по цене.

NullVoxPopuli
источник

Ответы:

66

Предполагая, что вы используете MySQL,

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

Обратите внимание на отличие от других ответов. updated_atКолонка будет полная метка времени, так что если вы хотите сортировать на основе день она была обновлена, вам нужно использовать функцию , чтобы получить только часть даты с отметки времени. В MySQL это так DATE().

Даниэль Вандерслуис
источник
7
Чтобы предотвратить случайное прерывание соединений с сообщениями "неоднозначный столбец", вам следует использовать следующую более надежную версию: :order => ["DATE(#{table_name}.updated_at)", :price](Обратите внимание, что :priceэто символ.)
Джо Лисс
Мне пришлось выйти из своей колонки заказов orderвот так:Model.all(:order => "day asc, `order` asc")
grant
149

В Rails 4 вы можете делать что-то подобное:

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

fooи barявляются столбцами в базе данных.

Кристиан Фаццини
источник
1
Rails 4 - лучший.
Дарт Эгрегиус
57
Thing.find(:all, :order => "updated_at desc, price asc")

сделает свое дело.

Обновить:

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

это путь Rails 3. (Спасибо @cpursley )

Эрик Эскобедо
источник
4
Спасибо, @Erik - я знаю, что это старый ответ, поэтому вот мое предупреждение для тех, кто его сейчас видит: этот метод устарел, начиная с Rails 3.2. Вместо этого используйте Thing.all =)
Abdo
Правильно, у меня это сработало: Thing.all.order("updated_at DESC, price ASC")
cpursley
1
Ваше обновление было полезно для меня , когда я нуждался в нижний регистр отсортированных значений: Thing.order("LOWER(name), number").
Ник
36

Интерфейс запросов Active Record позволяет вам указать столько атрибутов, сколько вы хотите упорядочить свой запрос:

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

или, если хотите уточнить (спасибо @ zw963 ):

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

Бонус: после первого запроса вы можете связать другие запросы:

models = models.where('date >= :date', date: Time.current.to_date)
Golfadas
источник
Я знаю, что это старый пост, но я бы лично изменил его modelна, modelsчтобы человек знал, что это множественное число. Просто предложение.
ТАСС
1
Думаю, следует отредактировать более конкретный пример: например, models = Model.order ({price:: desc}, {date:: desc}, {price: asc})
zw963
Если кто-то вставил это и увидел ошибку неопределенного метода, здесь есть небольшая опечатка. Это должно быть :ascвместо asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
nayiaw
18

На самом деле есть много способов сделать это с помощью Active Record. Тот, который не был упомянут выше, будет (в разных форматах, все допустимы):

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

Может быть, это более многословно, но лично мне легче управлять. SQL создается только за один шаг:

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

Таким образом, для исходного вопроса:

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

Вам не нужно объявлять тип данных, ActiveRecord делает это плавно, как и ваш механизм БД.

Рубиновый гонщик
источник
Это прекрасно работает при использовании двух столбцов из двух разных таблиц, таких как: Member.includes (: voter) .order ("town_club asc"). Order ("sizes.last_name asc")
bkunzi01
1
Соответствует ли опубликованный вами SQL Model.order(foo: :asc).order(:bar => :desc).order(:etc)? Порядок предложений порядка в SQL противоположен тому, что я получаю, когда запускаю его .to_sql.
Qaz
1
@Qaz, это было давно. Думаю, мне, наверное, нужно исправить это, я никогда не замечал. Я дважды проверю позже. Спасибо.
Ruby Racer
2
Model.all(:order => 'updated_at, price')
Робертокл
источник
0

Ни один из них не помог мне! Ровно через 2 дня поисков в Интернете я нашел решение !!

Допустим, у вас есть много столбцов в таблице продуктов, включая special_price и msrp. Это два столбца, по которым мы пытаемся выполнить сортировку.

Хорошо, сначала в вашей модели добавьте эту строку:

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

Во-вторых, в Product Controller добавьте, где вам нужно выполнить поиск:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Макс Александр Ханна
источник