通过has_many:通过关联检索ID的优化方法

时间:2014-02-18 18:18:44

标签: mysql sql ruby-on-rails ruby model

我有3个型号如下: (我也在描述数据库结构,以防任何不熟悉RubyOnRails的人能够帮助我)


Thread.rb

class Thread
  has_many :thread_profils
  has_many :profils, :through => :thread_profils
end

线程

integer: id (PK)

ThreadProfil.rb

class ThreadProfil
  belongs_to :thread
  belongs_to :profil
end

thread_profils

integer: id (PK)
integer: thread_id (FK)
integer: profil_id (FK)

Profil.rb

class Profil
end

个人资料

integer: id (PK)

在我的一个控制器中,我正在寻找最优化的方法来查找包含 完全 两个profils的线程ID(当前的一个,另一个是另一个) ):

我得到了current_profil.id和另一个profil.id,我无法找到一种简单的方法来获取Thread.id的集合/列表/数组,同时处理较少的SQL请求。


目前我发现的唯一解决方案是以下解决方案,我根本不认为它是“优化的”。

thread_profils = ThreadProfil.where(:profil_id => current_profil.id)
thread_ids = thread_profils.map do | association |
  profils = Thread.find(association.thread_id).profils.map do | profil | 
      profil.id if profil.id != current_profil.id
  end.compact
  if (profils - [id]).empty?
    association.thread_id
  end
end.compact

即处理以下SQL查询:

SELECT `thread_profils`.* FROM `thread_profils` WHERE `thread_profils`.`profil_id` = [current_profil.id]

每个结果:

SELECT `threads`.* FROM `threads` WHERE `threads`.`id` = [thread_id] LIMIT 1

SELECT `profils`.* FROM `profils` INNER JOIN `thread_profils` ON `profils`.`id` = `thread_profils`.`profil_id` WHERE `thread_profils`.`thread_id` = [thread_id]

有没有轻松的方法可以使用rails或直接使用SQL?

由于

1 个答案:

答案 0 :(得分:1)

我在sql中找到了以下查询:

SELECT array_agg(thread_id) FROM "thread_profils" WHERE "thread_profils"."profil_id" = 1 GROUP BY profil_id HAVING count(thread_id) =2

注意:array_agg是一个postgres聚合函数。 Mysql有group_concat,它会给你一个逗号分隔的ID字符串而不是数组。

这个sql是由以下Rails代码生成的:

 ThreadProfil.select('array_agg(mythread_id)').where(profil_id: 1).group(:profil_id).having("count(thread_id) =2").take

这会生成正确的查询,但结果对于ThreadProfil没有意义 - 但是,您可以继续使用它来获得所需的内容。