How to determine if a date range occurs any time within another date range?

↘锁芯ラ 提交于 2019-12-03 06:23:17

问题


I have an Event table that specifies a date range with start_date and end_date fields. I have another date range, specified in code, that defines the current week as 'week_start' and 'week_end'.

I'd like to query all Events for the week. The cases seem to be:

  • Event begins and ends within the week
  • Event begins before the week, but ends within the week
  • Event begins within the week, but ends after the week
  • Event begins before the week and also ends after the week
  • Events that neither reside within, nor overlap the week at all are ignored

I'm attempting to come up with a query that can handle all these cases. So far I've only been able to get cases that handle the week overlaps, or events that are fully internal; Essentially, too many records, or none at all.


回答1:


(event.start BETWEEN week.start AND week.end)
OR
(week.start BETWEEN event.start AND event.end)

In simple words, either a week starts during the event, or an event starts during the week.

Let's check it:

Event begins and ends within the week

The event starts during the week.

Event begins before the week, but ends within the week

The week starts during the event.

Event begins within the week, but ends after the week

The event starts during the week.

Event begins before the week and also ends after the week

The week starts during the event.

Note that BETWEEN in expressions above is used just for the sake of brevity.

Strict expression looks like this:

(event.start >= week.start AND event.start < week.end)
OR
(week.start >= event.start AND week.start < event.end)

, provided that week.end is a week.start + INTERVAL 7 DAY.

I. e. if you week starts of Sun, 0:00:00, then it should end on next Sun, 0:00:00 (not on Sat, 0:00:00)

This expression looks more complex than the one which is commonly used:

event.start < week.end AND event.end > week.start

, but the former is more efficient and index friendly.

See these articles in my blog for performance comparisons:

  • Overlapping ranges: SQL Server
  • Overlapping ranges: MySQL
  • Overlapping ranges: Oracle



回答2:


You could write your condition like this:

start_date <= week_end AND end_date >= week_start

Edit: this assumes start_date <= end_date and week_start <= week_end ( are properly ordered) and gives you the best performance on most db implementations due to not using OR (which on some databases may create performance issues)

Edit2: this solution also solves the problem of events that begin before the interval and end after the interval.




回答3:


+1 for pop Catalin, but alas I have no voting privilege.

The restrict condition you want is just the standard way to express Allen's "OVERLAPS" operator.

Additional SQL caveat : if end_date is nullable, be sure to treat nulls in those columns as "the end of time".

Additional functional caveat : be sure to adapt the usage of '<=' versus '<' to whether or not the recorded time periods include the end date or not.




回答4:


In order...

where start_date >= week_start and end_date <= week_end
where start_date <= week_start and end_date >= week_start and end_date <= week_end
where start_date >= week_start and start_date <= week_end and end_date > week_end
where start_date < week_start and end_date > week_end



回答5:


(end2 >= start1) && (start2 <= end1) I think would return true for any intersecting date ranges.

I found a discussion about this here that I found useful.



来源:https://stackoverflow.com/questions/730722/how-to-determine-if-a-date-range-occurs-any-time-within-another-date-range

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!