【问题标题】:Tricky SQL query with conditions from two tables带有来自两个表的条​​件的棘手 SQL 查询
【发布时间】:2018-03-09 13:16:43
【问题描述】:

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

我有一个 Ride 模型和一个 Driver 模型。 每个行程都有一个 schedule_at 和一个 driver_id (belongs_to) 字段。 创建新的 Ride 时,driver_id 为 NULL。然后司机可以接受还没有司机的游乐设施,因此向司机显示他可以接受的所有游乐设施,我在司机模型中创建:

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

棘手的部分是,我想从 open_rides 中排除所有游乐设施,其中司机已经在日期时间或接下来的 3 小时内有相同的 schedule_at 行程。

因此,换句话说,我想确保已经接受时间 X 乘车的司机在时间 X 和接下来的 3 小时内看不到任何乘车。

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

这是一个例子:

我的 Drivers 表中有一个 Driver:

{
  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。 Ride #2 还没有司机,但 Ride #2 的 schedule_at 在 3 小时范围内,距司机已经接受的另一个 Ride(在本例中是 Ride #1),因此不应包含在 open_rides 中。 Ride #3 没有司机,距离司机已经接受的行程超过 3 小时后,应将其包含在 open_rides 中。

【问题讨论】:

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


【解决方案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 添加一个 and 语句,如下所示:

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 方法中进行过滤,这可能更容易,但内存效率不高,因为会有大量的开放游乐设施。

【讨论】:

  • 扩展这个答案,在 Rails 中我们会写 Ride.where(driver_id: nil).where("(scheduled_at &lt; :date and scheduled_at &gt; :date + INTERVAL 3 HOUR) and (scheduled_at &lt; :date1 and scheduled_at &gt; :date1 + INTERVAL 3 HOUR) and (scheduled_at &lt; :date2 and scheduled_at &gt; :date1 + INTERVAL 3 HOUR)", date: some_date, date1: some_other_date, date2: other_date)
猜你喜欢
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
相关资源
最近更新 更多