Scope Order by Count with Conditions Rails

穿精又带淫゛_ 提交于 2021-01-27 12:27:46

问题


I have a model Category that has_many Pendencies. I would like to create a scope that order the categories by the amount of Pendencies that has active = true without excluding active = false.

What I have so far is:

scope :order_by_pendencies, -> { left_joins(:pendencies).group(:id).order('COUNT(pendencies.id) DESC')}

This will order it by number of pendencies, but I want to order by pendencies that has active = true.

Another try was:

scope :order_by_pendencies, -> { left_joins(:pendencies).group(:id).where('pendencies.active = ?', true).order('COUNT(pendencies.id) DESC')}

This will order by number of pendencies that has pendencies.active = true, but will exclude the pendencies.active = false.

Thank you for your help.


回答1:


I guess you want to sort by the amount of active pendencies without ignoring categories that have no active pendencies.

That would be something like:

scope :order_by_pendencies, -> { 
  active_count_q = Pendency.
    group(:category_id).
    where(active: true).
    select(:category_id, "COUNT(*) AS count")

  joins("LEFT JOIN (#{active_count_q.to_sql}) AS ac ON ac.category_id = id").
    order("ac.count DESC")
}

The equivalent SQL query:

SELECT *, ac.count 
FROM categories
LEFT JOIN (
    SELECT category_id, COUNT(*) AS count
    FROM pendencies
    GROUP BY category_id
    WHERE active = true
  ) AS ac ON ac.category_id = id
ORDER BY ac.count DESC

Note that if there are no active pendencies for a category, the count will be null and will be added to the end of the list. A similar subquery could be added to sort additionally by the total amount of pendencies...




回答2:


C# answer as requested:

method() {
    ....OrderBy((category) => category.Count(pendencies.Where((pendency) => pendency.Active))
}

Or in straight SQL:

SELECT category.id, ..., ActivePendnecies
  FROM (SELECT category.id, ..., count(pendency) ActivePendnecies
          FROM category
          LEFT JOIN pendency ON category.id = pendency.id AND pendnecy.Active = 1
          GROUP BY category.id, ...) P
 ORDER BY ActivePendnecies;

We have to output ActivePendnecies in SQL even if the code will throw it out because otherwise the optimizer is within its rights to throw out the ORDER BY.




回答3:


For now I developed the following (it's working, but I believe that it's not the best way):

  scope :order_by_pendencies, -> { scoped = Category.left_joins(:pendencies)
                                            .group(:id)
                                            .order('COUNT(pendencies.id) DESC')
                                            .where('pendencies.active = ?', true)
                                   all = Category.all
                                   (scoped + all).uniq}


来源:https://stackoverflow.com/questions/54611318/scope-order-by-count-with-conditions-rails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!