Sql 如何仅从联接表中选择唯一的条目

Sql 如何仅从联接表中选择唯一的条目,sql,ruby-on-rails,Sql,Ruby On Rails,我想让我的代码块更有效率。我有两个模型和一个连接表。他们都有一种通过的关系。有些零件属于多个组,有些零件只属于一个组。我需要以最有效的方式获取属于一个组的记录,因为有数千个部分。以下是我的模型: part.rb class Part < ActiveRecord::Base attr_accessible :name, :group_ids has_many :part_groups, dependent:

我想让我的代码块更有效率。我有两个模型和一个连接表。他们都有一种通过的关系。有些零件属于多个组,有些零件只属于一个组。我需要以最有效的方式获取属于一个组的记录,因为有数千个部分。以下是我的模型:

part.rb

class Part < ActiveRecord::Base
  attr_accessible     :name,
                      :group_ids

  has_many            :part_groups, dependent: :destroy
  has_many            :groups, through: :part_groups, select: 'groups.*, part_groups.*'
end
class Group < ActiveRecord::Base
  attr_accessible     :name,
                      :part_ids

  has_many            :part_groups, dependent: :destroy
  has_many            :parts, through: :part_groups, select: 'parts.*, part_groups.*'
end
class PartGroup < ActiveRecord::Base
  attr_accessible :part_id,
                  :group_id 


  belongs_to      :part
  belongs_to      :group
end

这显然是不可扩展的,因为将有许多组。我尝试了各种各样的
join
include
方法,我一直在谷歌上搜索,但到目前为止都没有效果

我也是rails新手,据我所知,这是您的表的结构

零件

Id| Name

团体

Id| Name

部分组

Id |部分|组| Id

因此,您可以执行以下操作:

Group.find(1).零件//零件属于A组

Group.find(2).部件//部件属于B组

因此,这可能会给出属于其他组的部件。 目标是获得仅属于A组和B组的零件

争取

Group.find(1).parts.collect{| row | row if row.groups.count==1}.flatten


我认为这比你的方法更好,因为我只遍历属于group1的那些部分。

这方面的原始sql可能如下所示

select parts.* from parts
inner join part_groups on parts.id = part_groups.part_id
left outer join part_groups as group_b on group_b.part_id = parts.id and group_b.group_id = 456
where group_b.id is null and part_groups.group_id = 123
假设a组id为123,b组id为456

这样做的目的是尝试连接part_groups表两次(因此需要第二次使用别名),一次连接组id与组A匹配,一次连接组B。使用左连接允许我们要求第二次连接(针对B)不生成行

Activerecord除了允许您将任意sql片段传递给
联接
,并没有为此提供太多帮助,因此您最终会得到如下结果

Part.select("parts.*").
      .joins(:part_groups).
      .joins("left outer join part_groups as group_b on group_b.group_id = #{groupb.id} and group_b.part_id = parts.id").
       .where(:part_groups => {:group_id => groupa.id}).where("group_b.id is null")

Arel(活动记录的查询生成部分的基础)可以生成此类查询,但不会直接公开。

这是设置,但每个都将返回两个组中的部分实例。例如,假设我有2个部分在
组A
,3个部分在
组B
,但
第1部分和
第4部分在
组A
组B
中<代码>组。查找(1)。parts
将返回
[part 1,part 2,part 4]
我只想返回
part 2
,因为它仅在
组A
中,对于小数据集,这应该可以正常工作,但是,对于较大的数据集,它将生成大量的DB请求,这将严重滞后于应用程序。这就是我为什么要寻找SQL解决方案的原因。
Part.select("parts.*").
      .joins(:part_groups).
      .joins("left outer join part_groups as group_b on group_b.group_id = #{groupb.id} and group_b.part_id = parts.id").
       .where(:part_groups => {:group_id => groupa.id}).where("group_b.id is null")