web-dev-qa-db-fra.com

Classement des rails par nombre de résultats de l'association has_many

Puis-je quand même ordonner les résultats (ASC/DESC) en fonction du nombre d'éléments renvoyés par le modèle enfant (Jobs)?

@featured_companies = Company.joins(:jobs).group(Job.arel_table[:company_id]).order(Job.arel_table[:company_id].count).limit(10)

Par exemple: je dois imprimer les entreprises avec les travaux les plus importants en haut

37
randika

Si vous envisagez d’utiliser cette requête fréquemment, je vous suggère d’utiliser le paramètre counter_cache

# Job Model
class Job < ActiveRecord::Base
  belongs_to :company, counter_cache: true
  # ...
end

# add a migration
add_column :company, :jobs_count, :integer, default: 0

# Company model
class Company < ActiveRecord::Base
  scope :featured, order('jobs_count DESC')
  # ...
end

et ensuite l'utiliser comme

@featured_company = Company.featured
36
Billy Chan

Rails 5+

La prise en charge des jointures externes gauches a été introduite dans Rails 5. Vous pouvez donc utiliser une jointure externe au lieu d'utiliser counter_cache pour le faire. De cette façon, vous garderez les enregistrements avec 0 relation:

Company
  .left_joins(:jobs)
  .group(:id)
  .order('COUNT(jobs.id) DESC')
  .limit(10)

L'équivalent SQL de la requête est le suivant (obtenu en appelant .to_sql dessus):

SELECT "companies".* FROM "companies" LEFT OUTER JOIN "jobs" ON "jobs"."company_id" = "companies"."id" GROUP BY "company"."id" ORDER BY COUNT(jobs.id) DESC
68
Sheharyar

Quelque chose comme:

Company.joins(:jobs).group("jobs.company_id").order("count(jobs.company_id) desc")
23
user24359

@ user24359 le bon devrait être:

Company.joins(:jobs).group("companies.id").order("count(companies.id) DESC")
20
Tan
Company.where("condition here...")
       .left_joins(:jobs)
       .group(:id)
       .order('COUNT(jobs.id) DESC')
       .limit(10)
0
faisal bhatti

Ajouté à la réponse de Tan. Pour inclure 0 association

Company.joins("left join jobs on jobs.company_id = companies.id").group("companies.id").order("count(companies.id) DESC")

par défaut, joins utilise une jointure interne. J'ai essayé d'utiliser left join pour inclure 0 association