简体   繁体   English

带有Rails ActiveRecord的左外部连接和where子句

[英]Left outer join and where clause with rails activerecord

I have two models : User and Rsvp. 我有两个模型:User和Rsvp。 User has many Rsvps. 用户有很多Rsvps。

I want to get all Users that has no Rsvp created at a specified date. 我想获取在指定日期没有创建Rsvp的所有用户。

So i wrote this : 所以我写了这个:

scope :free, -> (date) { joins(:rsvps).where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day}) }

But it only works if User has at least one Rsvp but not for 'date'. 但是,仅当用户至少具有一个Rsvp而不是“日期”时,它才起作用。 It doesn't work when a User has no Rsvp at all. 当用户完全没有Rsvp时,它将不起作用。

I tried with a left outer join, but it doesn't work. 我尝试了左外部联接,但是没有用。 I must miss something : 我一定想念一些东西:

scope :free, -> (date) { joins("LEFT OUTER JOIN rsvps ON rsvps.user_id = users.id").where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day}) }

Here's my unit test : 这是我的单元测试:

it 'should fetch user if he has no rsvp at all' do
  # Given
  user = User.create!(email: 'm@m.com', password: '12345678', password_confirmation: '12345678')

  # Then
  expect(User.free(Date.new(2014, 1, 1)).count).to eq 1
end

This should work: scope :free, -> (date) { includes(:rsvps).where("rsvps.id IS NULL OR rsvps.created_at NOT BETWEEN ? AND ?", date.beginning_of_day, date.end_of_day).references(:rsvps) } 这应该起作用: scope :free, -> (date) { includes(:rsvps).where("rsvps.id IS NULL OR rsvps.created_at NOT BETWEEN ? AND ?", date.beginning_of_day, date.end_of_day).references(:rsvps) }

Hope it helps! 希望能帮助到你!

It's normally that joins returns Users having at least one Rsvp. 通常, joins返回具有至少一个Rsvp的用户。 That's why I suggest using includes . 这就是为什么我建议使用includes的原因。 Try this one (probably you have to modify the condition because I'm not sure it's what you want exactly): 试试这个(可能您必须修改条件,因为我不确定它到底是不是您想要的):

scope :free, -> (date) { includes(:rsvps).where('rsvps.created_at != ?', date ).references(:rsvps) }

You almost got it right. 你几乎是对的。 You need to use a GROUP_BY statement so you don't get repeated rows. 您需要使用GROUP_BY语句,以免重复行。

scope :free, -> (date) do 
  joins("LEFT OUTER JOIN rsvps ON rsvps.user_id = users.id")
    .where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day})
    .group("users.id") # or just .group(:id)
end

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

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