按关联查找并按相关的counter_cache排序

时间:2012-09-12 18:16:47

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

我有很多相关的模型:

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)

现在,我需要找到所有公司并根据他们的订单对其进行排序,从最高到最低。由于我有群组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"
)

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

2 个答案:

答案 0 :(得分:0)

使用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")

答案 1 :(得分:0)

好的,这让我方式太长时间无法理解。我需要一本关于SQL ASAP的书。无论如何,这就是我想要的:

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]
)

:join将counter作为公司的column_name工作;为什么:包括不,我不知道,如果有人有一个很好的答案,我很想知道为什么。所以我可以写:

@companies.first.counter

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

修改

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

意识到rails连接使用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]
)

我现在也记得:包括急切的加载(不一定是连接),这可能是我无法使用它的原因。这在Rails 3中可能有所不同。请参见此处:Rails :include vs. :joins