注:1. 我们把第一步的查询结果放到临时表中,供下一步使用。
2. 车辆状态的枚举值请参见租车信息系统数据库设计(1)。车辆状态为Inuse表示此时该车正在被租用,不在车库中(但对于未来某段时间的预订,该车可能会有档期)。车辆状态和订单状态都有一个Inuse的枚举值,请不要混淆。
3. 此查询中的子查询可以用查出的ID值代替。
--2 在候选车辆中,选出在@StartDate和@EndDate之间有档期的车辆 select distinct CandidateCars.Car_ID into #CandidateCars2 from #CandidateCars1 CandidateCars left join Table_Order RentalOrder on CandidateCars.Car_ID = RentalOrder.Car_ID where ISNULL(RentalOrder.Order_BookStartDate, '9999-01-01') > @EndDate or ISNULL(RentalOrder.Order_BookEndDate, '1900-01-01') < @StartDate; |
到第二步结束我们的结果集中可能会有多辆符合条件的车。那到底选哪一辆车最合适呢?
我首先想到的是尽可能把车辆的档期排满。那就是一辆一辆的来排,第一辆排不下了,再排到第二辆,这样也许能使车辆的利用率最高。
但这种方案很快就被我排除了,原因有3个方面:
1. 这种方式会使某些车辆的租用很稠密,而另一些车可能一个订单都没有。
2. 某些车太稠密的订单容易产生意外情况,如前一个租车的顾客还车晚了,造成后面的顾客无法领到订单中的车辆。这种情况虽然可以通过临时更改车辆,但需要人为处理的意外境况增多了,且还需要修改原先的订单中的车辆信息。
3. 某些车太稠密的订单又会使某些车辆的使用率特别高,造成其维修率和折损率也特别高。
所以在第三步选车策略的目标是使每辆车的租用尽可能平均,车辆的租用间隔稀疏一些。相应的选车策略可以有:
1. 选从当前时间开始,被预订的时间总和最少的那辆车
2. 选从当前时间开始,被预订次数最少的那辆车
3. 选之前预订时间段与本次预订时间段前后间隔最大的那辆车
4. 随机选择一辆车
这几种策略哪个最好,我很难说,可能需要进行一些实验。大家可以思考讨论。
在这里我选择第3个策略来写查询。第3个策略相对于其他的策略从文字上稍难理解一些,我先来看一个图示:
图中是某辆车的预订时间轴,我希望本次预订期与之前的预订期之间的间隔尽可能大,这样当某顾客还车迟了时就能有多一些的缓冲时间。
要用SQL实现这一策略,我想到了2种算法:
1. 把前后间隔时间求和后倒序排列,取Top 1的记录
2. 先按与‘之前预订期1’的间隔时间倒序排列后取Top 2的2条记录,再拿这2条记录按与‘之前预订期2’的间隔时间倒序排列后取Top 1的记录