【问题标题】:Find and order by association's associated counter_cache按关联的 counter_cache 查找和排序
【发布时间】:2012-09-12 18:16:47
【问题描述】:

我有许多相关的模型:

Company has_many :clients (which belongs_to :company)  
Client has_many :groups (which belongs_to :client)
Group has_many :orders (which belongs_to :group, :counter_cache => true)

现在,我需要找到所有公司,并按照他们的订单从高到低对它们进行排序。因为我有 groups_orders_count 列,所以我很确定我可以按 groups.orders_count 排序。然后我需要遍历这些公司,显示旁边的总订单。

我一直在努力寻找这个。我有一个 MySQL 数据库,如果它归结为 find_by_sql 之类的。

companies = Company.find(
  :all,
  :include => { :clients => :groups },
  :select => "companies.*, groups.orders_count",
  :group => "companies.id",
  :order => "groups.orders_count"
)

任何帮助或推动正确的方向表示赞赏!谢谢。

【问题讨论】:

    标签: mysql ruby-on-rails ruby-on-rails-2


    【解决方案1】:

    使用groups.orders_count 可能是个问题。如果一家公司有两个客户并且每个客户都有一个组,那么您对哪个 group.orders_count 进行排序?如果我错了,请纠正我。

    这没有利用 counter_cache 但它应该可以工作(我的 Rails 2.x 有点生锈):

    companies = Company.all(
      :select => "companies.*",
      :include => { :clients =>  [ :groups => :orders ] },
      :group => "companies.id",
      :order => "count(orders.*) DESC")
    

    【讨论】:

    • 啊,我明白了,这样的排序是有道理的(尽管我认为它需要是 count(orders.id) DESC)。但是,我现在如何才能获得这些公司的数量,而无需遍历每个公司并手动进行哈希处理?
    【解决方案2】:

    好的,这花了我 方式 太久才弄明白。我需要尽快拿起一本关于 SQL 的书。无论如何,这就是我想要的:

    sql = "groups.created_at BETWEEN :start_date AND :end_date"
    options = { :start_date => 1.month.ago, :end_date => Date.today }
    
    @companies = Company.all(
      :select => 'companies.*, count(orders.id) as counter',
      :joins => { :clients => { :groups => :orders } },
      :group => 'companies.id',
      :order => 'counter DESC',
      :conditions => [sql, options]
    )
    

    :joins 使计数器作为公司的 column_name 工作;为什么 :includes 没有,我不知道,如果有人有一个很好的答案,我很想知道为什么。所以我可以写:

    @companies.first.counter
    

    并取回该公司的订单总数。

    编辑

    发现我得到了几乎我想要的结果,除了在某个日期范围内没有组/订单的客户。每个结果至少有 1 个计数器。

    意识到rails join使用INNER JOIN; LEFT JOIN 将返回没有相应子对象的对象。于是我改成了这样:

    @companies = Company.all(
      :select => 'companies.*, count(orders.id) as counter',
      :joins => "LEFT JOIN clients ON clients.company_id = companies.id
        LEFT JOIN groups ON groups.client_id = clients.id LEFT JOIN orders ON orders.group_id = groups.id",
      :group => 'companies.id',
      :order => order_by,
      :conditions => [sql, options]
    )
    

    我现在还记得 :includes 急切加载(不一定要加入),这可能是我不能使用它的原因。这在 Rails 3 中可能有所不同。请参阅此处:Rails :include vs. :joins

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多