Ruby on Rails:如何使用ActiveRecord对两列进行排序?

Nul*_*uli 83 ruby-on-rails

我想按两列排序,一个是DateTime(updated_at),另一个是十进制(Price)

我希望能够先使用updated_at进行排序,然后,如果同一天出现多个项目,则按价格排序.

Chr*_*ini 135

在Rails 4中,你可以做类似的事情:

Model.order(foo: :asc, bar: :desc)
Run Code Online (Sandbox Code Playgroud)

foo并且bar是db中的列.

  • 非常非常棒 !! (2认同)

Dan*_*uis 62

假设您正在使用MySQL,

Model.all(:order => 'DATE(updated_at), price')
Run Code Online (Sandbox Code Playgroud)

请注意与其他答案的区别.该updated_at列将是一个完整的时间戳,因此如果您想根据更新的日期进行排序,则需要使用一个函数来从时间戳中获取日期部分.在MySQL中,就是这样DATE().

  • 要使用"模糊列"消息随意断开连接,你应该使用以下更强大的版本:`:order => ["DATE(#{table_name} .updated_at)",:price]`(注意`:price `是一个符号.) (7认同)

Eri*_*edo 54

Thing.find(:all, :order => "updated_at desc, price asc")
Run Code Online (Sandbox Code Playgroud)

会做的.

更新:

Thing.all.order("updated_at DESC, price ASC")
Run Code Online (Sandbox Code Playgroud)

是目前的方式.(谢谢@cpursley)

  • 谢谢你@Erik - 我知道这个答案已经过时了,所以这里是我对那些现在看到它的警告:这个方法已经被弃用,从Rails 3.2开始.使用Thing.all代替=) (4认同)

gol*_*das 28

Active Record Query Interface允许您指定要为查询订购的任意数量的属性:

models = Model.order(:date, :hour, price: :desc)
Run Code Online (Sandbox Code Playgroud)

或者如果你想更具体(感谢@ zw963):

models = Model.order(price: :desc, date: :desc, price: :asc) 
Run Code Online (Sandbox Code Playgroud)

奖励:在第一次查询后,您可以链接其他查询:

models = models.where('date >= :date', date: Time.current.to_date)
Run Code Online (Sandbox Code Playgroud)


Rub*_*cer 17

实际上有很多方法可以使用Active Record来实现.上面没有提到的将是(以各种格式,全部有效):

Model.order(foo: :asc).order(:bar => :desc).order(:etc)
Run Code Online (Sandbox Code Playgroud)

也许它更冗长,但我个人觉得它更容易管理.SQL仅在一步中生成:

SELECT "models".* FROM "models" ORDER BY "models"."etc" ASC, "models"."bar" DESC, "models"."foo" ASC
Run Code Online (Sandbox Code Playgroud)

因此,对于原始问题:

Model.order(:updated_at).order(:price)
Run Code Online (Sandbox Code Playgroud)

您无需声明数据类型,ActiveRecord可以顺利地执行此操作,您的数据库引擎也是如此