简体   繁体   English

Rails通过关联记录数进行选择

[英]Rails select by number of associated records

I have following models in my rails app: 我的rails应用程序中有以下模型:

class Student < ApplicationRecord
  has_many :tickets, dependent: :destroy
  has_and_belongs_to_many :articles, dependent: :destroy

class Article < ApplicationRecord
  has_and_belongs_to_many :students, dependent: :destroy

class Ticket < ApplicationRecord
  belongs_to :student, touch: true

I need to extract all Students who has less than articles and I need to extract all Students who's last ticket title is 'Something'. 我需要提取所有少于文章的学生,并且我需要提取所有最后一个票证标题为“ Something”的学生。

Everything I tried so far takes a lot of time. 到目前为止,我尝试的所有操作都需要花费大量时间。 I tried mapping and looping through all Students. 我尝试过映射和遍历所有学生。 But I guess what I need is a joined request. 但是我想我需要的是一个联合请求。 I am looking for the most efficient way to do it, as database I am working with is quite large. 我正在寻找最有效的方法,因为我正在使用的数据库很大。

You asked "I need to extract all Students who has less than articles" . 您问"I need to extract all Students who has less than articles" I'll presume you meant "I need to extract all Students who have less than X articles" . 我假设您是说"I need to extract all Students who have less than X articles" In that case, you want group and having https://guides.rubyonrails.org/active_record_querying.html#group . 在这种情况下,您需要grouphaving https://guides.rubyonrails.org/active_record_querying.html#group

For example, Article.group(:student_id).having('count(articles.id) > X').pluck(:student_id) . 例如, Article.group(:student_id).having('count(articles.id) > X').pluck(:student_id)

To address your second question, you can use eager loading https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations to speed up your code. 要解决第二个问题,您可以使用急切加载https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations来加快代码的速度。

result = students.filter do |student|
  students.tickets.last.name == 'Something'
end

go with @MCI's answer for your first question. 对于第一个问题,请使用@MCI的答案。 But a filter/select/find_all or whatever (although I havn't heared about filter method in ruby) through students record takes n queries where n is the number of student records (called an n+1 query). 但是,通过学生记录进行filter / select / find_all或其他任何操作(尽管我还没有听说过ruby中的过滤方法)需要进行n次查询,其中n是学生记录的数量(称为n + 1查询)。

studs = Student.find_by_sql(%{select tmp.id from (
  select student_id as id from tickets where name='Something' order by tickets.created_at desc
) tmp group by tmp.id})

Here association is HABTM so below query should work 这里的关联是HABTM,因此下面的查询应该有效

x = 10
Student.joins(:articles).group("articles_students.student_id").having("count(articles.id) < ?",x)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM