我已经尝试了一段时间解决这个问题了。 我搜索了很多,但似乎没有人有类似的问题。
这是我得到的:
Table 1 / Schedule
EmployeeID, PStart, PEnd
1, 2016-07-01 08:00:00, 2016-07-01 12:00:00
1, 2016-07-01 13:00:00, 2016-07-01 17:00:00
Table 2 / Bookings
EmployeeID, PStart, PEnd
1, 2016-07-01 08:00:00, 2016-07-01 08:40:00
1, 2016-07-01 09:00:00, 2016-07-01 10:10:00
1, 2016-07-01 10:30:00, 2016-07-01 11:00:00
1, 2016-07-01 13:00:00, 2016-07-01 15:00:00
1, 2016-07-01 15:00:00, 2016-07-01 15:30:00
我想比较这两张表并获得时间表和预订时间之间的差距。没有预订的时间。
在这个例子中
Result table / Not booked
EmployeeID, PStart, PEnd
1, 2016-07-01 08:40:00, 2016-07-01 09:00:00
1, 2016-07-01 10:10:00, 2016-07-01 10:30:00
1, 2016-07-01 11:00:00, 2016-07-01 12:00:00
1, 2016-07-01 15:30:00, 2016-07-01 17:00:00
查询的速度非常重要。员工人数超过150,所以行数很多。 我们将要使用的日期范围可能是有限的(例如,获得两周的差距),而不是显示自开始时间以来的所有差距。但只有这有助于查询速度。
提前致谢。
此致 亚当
答案 0 :(得分:2)
您可以使用CTE和if(isNewInstance) {
if(ctx.instance.needToUpdate){
process.nextTick(() => {
ctx.instance.updateAttributes();
});
}
} else {
}
窗口函数的组合来完成此操作。
这个想法:
以下是使用上述数据执行此操作的示例代码:
ROW_NUMBER()
编辑:这不适用于预订在时间表结束时。因为将选择不同的字段,所以对其进行排序的方法是使用;with allRows as
(
-- give each booking an increasing row
select ROW_NUMBER() OVER (PARTITION BY scheduleRow ORDER BY scheduleRow, b.PStart, b.PEnd) bookingRow,
s.EmployeeId,
s.scheduleRow,
s.PStart as scheduleStart,
s.PEnd as scheduleEnd,
b.PStart as bookingStart,
b.PEnd as bookingEnd
from
(
-- we need to add an id for our schedules (does it exist in your case?)
select ROW_NUMBER() OVER (ORDER BY PStart, PEnd) scheduleRow, *
FROM schedule
) s
left join bookings b on -- so we can get schedules without bookings
s.employeeID = b.employeeID AND
s.PStart <= b.PEnd AND
s.PEnd >= b.PStart
)
select
bookingLeft.EmployeeId,
ISNULL(bookingLeft.bookingEnd, bookingLeft.scheduleStart) as PStart,
ISNULL(bookingRight.bookingStart, bookingLeft.scheduleEnd) as PEnd
from allRows bookingLeft
left join allRows bookingRight on
-- this joins the row to the one BELOW for the schedule
bookingLeft.scheduleRow = bookingRight.scheduleRow and
bookingLeft.bookingRow = bookingRight.bookingRow - 1
where
-- this finds our gaps because the end of the last booking
-- doesn't touch the start of the next booking.
ISNULL(bookingLeft.bookingEnd, bookingLeft.scheduleStart) < ISNULL(bookingRight.bookingStart, bookingLeft.scheduleEnd)
。因此,可以将其添加到主脚本中,以考虑最后的预订。
UNION
如果您使用的是SQL 2012及更高版本,则可以使用LEAD(),这将消除union all -- a bit quicker than a straight UNION
select
bookingLeft.EmployeeId,
ISNULL(bookingRight.bookingEnd, bookingLeft.scheduleStart),
bookingLeft.bookingStart
from allRows bookingLeft
left join allRows bookingRight on
-- this joins the row to the one ABOVE for the schedule
bookingLeft.scheduleRow = bookingRight.scheduleRow and
bookingLeft.bookingRow = bookingRight.bookingRow + 1
where
ISNULL(bookingRight.bookingEnd, bookingLeft.scheduleStart) < bookingLeft.bookingStart and
bookingLeft.bookingEnd >= bookingLeft.scheduleEnd -- special case when booking at the end of a schedule
CTE,使查询更小。
至于性能,你可以将allRows写入临时表,打上索引,然后从中查询 - 它应该非常快。