具有两个表条件的棘手SQL查询

时间:2018-03-09 13:16:43

标签: mysql sql ruby-on-rails activerecord ruby-on-rails-5

我正在开发一个Rails 5应用程序。

我有一个Ride模型和一个Driver模型。 每次骑行都有一个scheduled_at和一个driver_id(belongs_to)字段。 创建新的Ride时,driver_id为NULL。然后,驱动程序可以接受没有驱动程序的游戏,因此要显示我可以接受的所有游戏,我可以接受我在我的游戏模型中创建的游戏:

def open_rides    
   Ride.where('driver_id IS NULL')
end

棘手的部分是我想要从open_rides中排除所有游戏,其中游戏已经具有相同的scheduled_at日期时间或接下来的3个小时。

所以换句话说,我想确保已经接受了X次骑行的驾驶员在时间X和接下来的3个小时内看不到任何骑行。

我希望能够在我的open_rides方法中将其表示为WHERE,但是非常欢迎任何其他想法。

以下是一个例子:

我的驱动程序表中有一个驱动程序:

{
  id: 1,
  name: 'Thommy'
}

我的游乐设施表中有3个游乐设施:

{
  id: 1,
  scheduled_at: 2018-04-04 12:00:00,
  driver_id: 1
},
{
  id: 2,
  scheduled_at: 2018-04-04 13:00:00,
  driver_id: NULL
},
{
  id: 3,
  scheduled_at: 2018-04-04 20:00:00,
  driver_id: NULL
}

司机已经分配到骑行#1。乘坐#2还没有驾驶员,但是驾驶#2的scheduled_at在驾驶员已经接受的另一个驾驶的3小时范围内(在这种情况下是乘坐#1)所以它不应该包含在open_rides中)。 乘坐#3没有驾驶员,并且在驾驶员已经接受驾驶之后超过3小时它应该包含在open_rides中。

1 个答案:

答案 0 :(得分:1)

你的open_rides方法应该在3小时范围之外查询具有NULL driver_id的游乐设施,因此你必须通过所有预定的驱动器日期(dateParam列表)来过滤掉方法。

select * from ride
where driver_id is null
and (scheduled_at < @dateParam and scheduled_at > @dateParam + INTERVAL 3 HOUR)

您必须在驱动程序保留的日期列表中为每个dateParam添加一个和语句,如下所示:

select * from ride
    where driver_id is null
    and (scheduled_at < @dateParam and scheduled_at > @dateParam + INTERVAL 3 HOUR)
and (scheduled_at < @dateParam1 and scheduled_at > @dateParam1 + INTERVAL 3 HOUR)
and (scheduled_at < @dateParam2 and scheduled_at > @dateParam1 + INTERVAL 3 HOUR)

我对MySQL或Rails并不熟悉,但我想你可以这样做,虽然它可能是最好的方法,但它会将处理留给数据库。 另一种选择是使用driver_id null加载所有游乐设施,并在open_rides方法中进行过滤,这可能更容易,但内存效率不高,因为会有大量的开放游乐设施。