Rails在一个查询中保留了连接和内连接

时间:2018-03-09 12:26:01

标签: sql ruby-on-rails ruby postgresql ruby-on-rails-5

问题是如何找到没有关联 OR 的所有记录与字段不等于给定字符串的关联:

class Group < ApplicationRecord
  has_many :administration_groups
  has_many :administrations, through: :administration_groups
end

class AdministrationGroup < ApplicationRecord
  belongs_to :administration
  belongs_to :group
end

class Administration < ApplicationRecord
  has_many :administration_groups
  has_many :groups, through: :administration_groups
end

那么我如何才能获得所有没有主管部门或拥有主管部门但是具有“管理”类型的群组。不等于&#39; type1&#39;?

groups_1 = Group.left_joins(:administration_groups).where(administration_groups: {id: nil})

groups_2 = Group.joins(administration_groups: [:administration]).where.not(administrations: {administration_type: params[:type]})

我有两个查询,但我无法将它们组合起来以获得所需的结果。感谢任何帮助

2 个答案:

答案 0 :(得分:0)

尝试此查询:

groups = Group.left_joins(:administrations).where(
  "administrations.id is NULL OR
   administrations.administration_type != ?", params[:type]
)

答案 1 :(得分:0)

您可以使用这两个查询中的ID,您可以使用orActiveRecord::Relations合并在一起,如下所示:

Group.where.not(id: 
  Group.joins(:administration_groups)
  .pluck(:id)
).or(
Group.where(id: 
  Group
    .joins(administration_groups: :administration)
       .where.not(administrations: {administration_type: params[:type]}).pluck(:id)
)) 

哪个应该导致类似于

的查询
 SELECT 
   [groups].*
 FROM 
   [groups] 
 WHERE
   ([groups].[id] NOT IN (
      SELECT 
         [groups].[id] 
      FROM 
         [groups] 
         INNER JOIN [administration_groups] 
           ON [administration_groups].[group_id] = [groups].[id])
   ) OR (
     [groups].[id] IN ( 
     SELECT 
         [groups]. [id] 
     FROM 
         [groups] 
         INNER JOIN [administration_groups] 
            ON [administration_groups].[group_id] = [groups].[id]
         INNER JOIN [administrations] 
           ON [administrations].[id] = [administration_groups].[administration_id] 
     WHERE 
           [administrations].[administration_type] <> YOUR_PARAMS_TYPE)
  )

此外,这也可行:

Group.where.not(id: 
  Group
    .joins(administration_groups: :administration)
       .where(administrations: {administration_type: params[:type]}).pluck(:id))

这将导致

SELECT 
  [groups].*
FROM 
  [groups]
WHERE 
  [groups].[id] NOT IN (
     SELECT 
         [groups]. [id] 
     FROM 
         [groups] 
         INNER JOIN [administration_groups] 
            ON [administration_groups].[group_id] = [groups].[id]
         INNER JOIN [administrations] 
           ON [administrations].[id] = [administration_groups].[administration_id] 
     WHERE 
           [administrations].[administration_type] = YOUR_PARAMS_TYPE
  )

由于[administration_groups]上的INNER JOIN已经删除了NULL值,因此类型检查将包含您不想包含的其他ID。