【问题标题】:Ruby on Rails: how do I sort with two columns using ActiveRecord?Ruby on Rails:如何使用 ActiveRecord 对两列进行排序?
【发布时间】:2010-08-27 20:09:29
【问题描述】:

我想按两列排序,一列是 DateTime (updated_at),另一列是 Decimal (Price)

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

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    在 Rails 4 中,您可以执行以下操作:

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

    foobar 是数据库中的列。

    【讨论】:

      【解决方案2】:

      假设您使用的是 MySQL,

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

      注意与其他答案的区别。 updated_at 列将是一个完整的时间戳,所以如果你想根据它更新的 day 进行排序,你需要使用一个函数来从时间戳中获取日期部分。在 MySQL 中,即为DATE()

      【讨论】:

      • 要阻止连接随机破坏“不明确的列”消息,您应该使用以下更强大的版本::order => ["DATE(#{table_name}.updated_at)", :price](请注意,:price 是一个符号。)
      • 我不得不用order 转义我的订单列,就像这样:Model.all(:order => "day asc, `order` asc")
      【解决方案3】:
      Thing.find(:all, :order => "updated_at desc, price asc")
      

      会成功的。

      更新:

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

      是 Rails 3 的发展方向。 (感谢@cpursley

      【讨论】:

      • 谢谢@Erik - 我知道这个答案已经过时了,所以这是我对现在看到它的人的警告:从 Rails 3.2 开始,此方法已被弃用。改用 Thing.all =)
      • 正确,这对我来说效果很好:Thing.all.order("updated_at DESC, price ASC")
      • 当我需要将排序后的值小写时,您的更新对我很有帮助:Thing.order("LOWER(name), number")
      【解决方案4】:

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

      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)
      

      【讨论】:

      • 我知道这是一篇旧帖子,但我会亲自将model 更改为models,以便人们知道它是复数形式。只是一个建议。
      • 我认为应该编辑一个更特别的例子:例如模型 = Model.order({price: :desc}, {date: :desc}, {price: asc})
      • 如果有人粘贴这个并看到未定义的方法错误,这里有一个小错字。它应该是:asc 而不是ascModel.order({price: :desc}, {date: :desc}, {price: :asc})
      【解决方案5】:

      实际上,使用 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 可以顺利完成此操作,您的 DB Engine 也是如此

      【讨论】:

      • 这在使用来自两个不同表的两列时非常有用,例如:Member.includes(:voter).order("town_club asc").order("voters.last_name asc")
      • 你发布的SQL是否对应Model.order(foo: :asc).order(:bar => :desc).order(:etc)? SQL 中 order 子句的顺序与我在其上运行 .to_sql 时得到的相反。
      • @Qaz 这是很久以前的事了。我想我可能需要纠正这个,我从来没有注意到。稍后我会仔细检查。谢谢。
      【解决方案6】:
      Model.all(:order => 'updated_at, price')
      

      【讨论】:

        【解决方案7】:

        这些都不适合我! 在网上查了整整 2 天后,我找到了解决方案!

        假设您在产品表中有许多列,包括:special_price 和 msrp。这是我们尝试排序的两列。

        好的,首先在你的模型中 添加这一行:

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

        其次,在产品控制器中,添加您需要执行搜索的位置:

        @search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-25
          • 2014-07-03
          • 1970-01-01
          • 1970-01-01
          • 2010-11-23
          相关资源
          最近更新 更多