【问题标题】:Rails advance ordering with SQLRails 使用 SQL 提前订购
【发布时间】:2018-08-10 11:21:09
【问题描述】:

我有用户模型,它具有一些属性,例如 is_admin、is_verified,并且还与其他模型(例如徽章和活动)关联。

我在 HTML 中有表格设计,默认情况下,用户将按 is_verified 排序,然后是 is_admin,然后是徽章数量,然后是活动数量。但我不知道如何创建一个。

我试过这样的示例代码:

users = User.all.limit(10)
users.order(is_verified: :true).order(is_admin: :true).order(users.map{|user| user.badges.count}).order(users.map{|user| user.activites.count})

但这不起作用,因为订单只接受:asc, :desc, :ASC, :DESC, "asc", "desc", "ASC", "DESC"]

您有什么新方法可以做到这一点,我是新来查询的吗?非常感谢您的帮助。

我有这样的示例设计:

【问题讨论】:

    标签: sql ruby-on-rails postgresql sqlite


    【解决方案1】:

    order 接受多个参数,因此您可以使用以下内容:

    users.order(is_verified: :desc, is_admin: :desc)
         .order('badges_count DESC', 'activities_count DESC')
    

    对于boolean 列,它们通常以1 用于true0 用于false 存储在数据库中,因此desc 方向。如果您没有将这些列默认为一个或另一个(大概是false),您可能需要调整为(即)order("is_verified DESC NULLS LAST", ...)

    这需要一些重构才能有效运行,依靠counter_caches 来获取徽章和活动。如果您要定期查询此内容,我强烈建议您添加此内容。有一个很好的指南here

    只需要:

    • activities_countbadges_count 的新列
    • counter_cache: true 设置在关联的 belongs_to 一侧
    • 使用this method 重置的计数器,即User.reset_counters(:badges, :activities)

    否则原样,您可以使用:

    User.left_joins(:badges, :activities)
        .order(is_verified: :desc, is_admin: :desc)
        .group("badges.id", "activities.id")
        .order('COUNT(badges.id) DESC', 'COUNT(activities.id) DESC')
    

    如果您对它的输出感到好奇,您可以致电to_sql 以了解它实际上是如何从数据库中调用数据的。

    试一试,让我知道您的进展情况 - 如果您有任何问题,我们很乐意为您提供帮助!

    【讨论】:

    • 非常感谢您,先生。我收到了这个错误ActiveRecord::StatementInvalid: SQLite3::SQLException: misuse of aggregate: COUNT()
    • 不客气。而且啊 - 想我可能错过了group... 一秒钟,我会更新答案。
    • 联接将排除具有零关联记录的记录,左外联接将是正确的选择。
    • 谢谢 - 我已经更新了答案。 @chronycles - 更新为包含分组。
    • "如果您想选择一组记录,无论它们是否有关联记录,您都可以使用 left_outer_joins 方法。" - 链接here。这意味着它将包括 badges / activities 为零的记录;加入不会。
    【解决方案2】:

    您可以尝试使用数据库本身进行排序,这比对加载的记录数组执行排序要快。默认情况下,如果您按降序对任何布尔字段进行排序,则所有布尔值为 true 的记录将排在第一位。最终查询可能看起来像,

    User.order(is_verified: :desc).order(is_admin: :desc).
      left_joins(:badges).
      group(:id).
      order("count(badges.id) desc")
      left_joins(:activities)
      group(:id).
      order("count(activities.id) desc")
    

    左连接(左外连接)包括具有零个或多个关联记录的文档。您可以在the documentation page 中找到详细信息。

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      • 2015-12-04
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多