Sql Rails用于没有特定子记录的父记录的作用域

Sql Rails用于没有特定子记录的父记录的作用域,sql,ruby-on-rails,ruby,postgresql,Sql,Ruby On Rails,Ruby,Postgresql,我有一个父模型的工作,已经分裂了很多次: class Effort has_many :split_times end class SplitTime belongs_to :effort belongs_to :split end class Split has_many :split_times enum kind: [:start, :finish, :intermediate] end 我需要一个范围,它将返回没有开始时间的工作。这似乎是可能的,但到目前为止我还

我有一个父模型的工作,已经分裂了很多次:

class Effort
  has_many :split_times
end

class SplitTime
  belongs_to :effort
  belongs_to :split
end

class Split
  has_many :split_times
  enum kind: [:start, :finish, :intermediate]
end
我需要一个范围,它将返回没有开始时间的工作。这似乎是可能的,但到目前为止我还不能做到

我可以通过以下方式回报我的努力,而不需要任何时间:

scope :without_split_times, -> { includes(:split_times).where(split_times: {:id => nil}) }
scope :with_split_times, -> { joins(:split_times).uniq }
我可以通过以下方式回报至少有一次拆分时间的工作:

scope :without_split_times, -> { includes(:split_times).where(split_times: {:id => nil}) }
scope :with_split_times, -> { joins(:split_times).uniq }
以下是我对所需范围的尝试:

scope :without_start_time, -> { joins(split_times: :split).where(split_times: {:id => nil}).where('splits.kind != ?', Split.kinds[:start]) }

但这不起作用。我需要的东西,将返回所有的努力,没有一个分裂的时间,有一个分裂与种类::开始,即使努力有其他分裂的时间。我更喜欢Rails解决方案,但如有必要,可以使用原始SQL。如果有必要的话,我会使用Postgres。

您可以根据您的条件(即
splits.kind='start'
)保留连接,该条件将包括空值(即没有匹配的行要连接)。不同之处在于Rails的
join
默认情况下会给您一个内部联接(两个表中都有匹配的行),但您需要一个左联接,因为您需要检查右表中是否没有匹配的行

根据该联接的结果,您可以按事件分组,然后计算匹配的拆分数量-如果为0,则该事件没有匹配的开始拆分

这可能对您有好处:

scope :without_start_time, -> { 
  joins("LEFT JOIN split_times ON split_times.effort_id = efforts.id").
    joins("LEFT OUTER JOIN splits ON split_times.split_id = splits.id " \
          "AND splits.kind = 0").
    group("efforts.id").
    having("COUNT(splits.id) = 0")
}

您可以尝试左连接:
Effort.joins('left join split_times ON split_times.Effort_id=efforcess.id')。其中('split_times.id为NULL')
@user3309314,它只返回根本没有拆分时间的工作。我想返回已拆分\u次的工作,只要拆分\u次都与开始拆分无关。这种语法在一些地方是错误的,但即使在修复了问题之后,它也会返回一个包含数千条工作记录的关系,其中应该只返回少量。下面是SQL:
选择“努力”。*从“努力”中选择“努力”内部连接“分割时间”。“努力时间id”=“努力”。“id”在分割时间上左连接分割。“分割时间id=splits.id和splits.kind=0,其中“分割”。“id”为空限制$1[“限制”,11]
@moveson这已接近。只要没有一个分割时间是开始分割时间,它就会返回分割分割时间的工作。但它也应该返回完全没有拆分时间的工作,而且它不会这样做。@moveson这是通过将左连接更改为左外部连接,将内部连接更改为左连接来解决的-已更新!