我正在尝试使用多种资源创建预订系统:日历#1和日历#2。日历本身不包含重叠范围。一个日历中的范围可以跨越另一个日历中的多个范围。
请参阅下面或sqlfiddle
上的架构和数据 Events on Calendar #1
ID startDate endDate
-----------------------------------------------
1 2012-01-01 02:00:00 2012-01-01 03:00:00
2 2012-01-01 05:00:00 2012-01-01 07:00:00
3 2012-01-01 09:00:00 2012-01-01 11:00:00
4 2012-01-01 16:00:00 2012-01-01 18:00:00
5 2012-01-01 19:00:00 2012-01-01 22:00:00
6 2012-02-02 10:00:00 2012-02-02 20:00:00
7 2012-03-03 05:00:00 2012-03-03 07:00:00
8 2012-03-03 09:00:00 2012-03-03 11:00:00
9 2012-03-03 12:00:00 2012-03-03 14:00:00
10 2012-03-03 15:00:00 2012-03-03 17:00:00
11 2012-03-03 19:00:00 2012-03-03 21:00:00
12 2012-03-03 22:00:00 2012-03-03 23:00:00
Events on Calendar #2
ID startDate endDate
-----------------------------------------------
1 2012-01-01 01:00:00 2012-01-01 04:00:00
2 2012-01-01 06:00:00 2012-01-01 08:00:00
3 2012-01-01 12:00:00 2012-01-01 14:00:00
4 2012-01-01 15:00:00 2012-01-01 17:00:00
5 2012-01-01 20:00:00 2012-01-01 21:00:00
6 2012-02-02 05:00:00 2012-02-02 07:00:00
7 2012-02-02 09:00:00 2012-02-02 11:00:00
8 2012-02-02 12:00:00 2012-02-02 14:00:00
9 2012-02-02 15:00:00 2012-02-02 17:00:00
10 2012-02-02 19:00:00 2012-02-02 21:00:00
11 2012-02-02 22:00:00 2012-02-02 23:00:00
12 2012-03-03 10:00:00 2012-03-03 20:00:00
2012-01-01:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
Cal#1 |--| |-----| |-----| |-----| |--------|
Cal#2 |--------| |-----| |-----| |-----| |--|
2012-02-02:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
Cal#1 |-----------------------------|
Cal#2 |-----| |-----| |-----| |-----| |-----| |--|
2012-03-03:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
Cal#1 |-----| |-----| |-----| |-----| |-----| |--|
Cal#2 |-----------------------------|
a)如何在两个日历中找到的间隔:
startDate endDate
-----------------------------------------------
2012-01-01 02:00:00 2012-01-01 03:00:00
2012-01-01 06:00:00 2012-01-01 07:00:00
2012-01-01 16:00:00 2012-01-01 17:00:00
2012-01-01 20:00:00 2012-01-01 21:00:00
2012-02-02 10:00:00 2012-02-02 11:00:00
2012-02-02 12:00:00 2012-02-02 14:00:00
2012-02-02 15:00:00 2012-02-02 17:00:00
2012-02-02 19:00:00 2012-02-02 20:00:00
2012-02-03 10:00:00 2012-02-03 11:00:00
2012-02-03 12:00:00 2012-02-03 14:00:00
2012-02-03 15:00:00 2012-02-03 17:00:00
2012-02-03 19:00:00 2012-02-03 20:00:00
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
01 Cal#1&2 |--| |--| |--| |--|
02 Cal#1&2 |--| |-----| |-----| |--|
03 Cal#1&2 |--| |-----| |-----| |--|
b)如何在#1中找到但在#2 中找不到间隔:
startDate endDate
-----------------------------------------------
2012-01-01 05:00:00 2012-01-01 06:00:00
2012-01-01 09:00:00 2012-01-01 11:00:00
2012-01-01 17:00:00 2012-01-01 18:00:00
2012-01-01 19:00:00 2012-01-01 20:00:00
2012-01-01 21:00:00 2012-01-01 22:00:00
2012-02-02 11:00:00 2012-02-02 12:00:00
2012-02-02 14:00:00 2012-02-02 15:00:00
2012-02-02 17:00:00 2012-02-02 19:00:00
2012-03-03 05:00:00 2012-03-03 07:00:00
2012-03-03 09:00:00 2012-03-03 10:00:00
2012-03-03 20:00:00 2012-03-03 21:00:00
2012-03-03 22:00:00 2012-03-03 23:00:00
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
01 Cal#1-2 |--| |-----| |--| |--| |--|
02 Cal#1-2 |--| |--| |-----|
03 Cal#1-2 |-----| |--| |--| |--|
c)如何在日历/间隔范围内外的任何地方的START和END之间的没有日历中找到间隔。
startDate endDate
-----------------------------------------------
START:2012-01-01 04:30:00 2012-01-01 05:00:00
2012-01-01 08:00:00 2012-01-01 09:00:00
2012-01-01 11:00:00 2012-01-01 12:00:00
2012-01-01 14:00:00 2012-01-01 15:00:00
2012-01-01 18:00:00 2012-01-01 19:00:00
2012-01-01 22:00:00 2012-02-02 05:00:00
2012-02-02 07:00:00 2012-02-02 09:00:00
2012-02-02 21:00:00 2012-02-02 22:00:00
2012-02-02 23:00:00 2012-03-03 05:00:00
2012-03-03 07:00:00 END:2012-03-03 07:30:00
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
01 Cal-1-2 |-| |--| |--| |--| |--| |------
02 Cal-1-2 ---------------| |-----| |--| |---
03 Cal-1-2 ---------------| |-END
答案 0 :(得分:1)
如何在两个日历中找到的间隔:
SELECT GREATEST(Cal1.startDate, Cal2.startDate) AS startDate,
LEAST(Cal1.endDate , Cal2.endDate ) AS endDate
FROM Cal1 JOIN Cal2
ON Cal2.startDate BETWEEN Cal1.startDate AND Cal1.endDate
OR Cal1.startDate BETWEEN Cal2.startDate AND Cal2.endDate
如何在#1中找到间隔,而不是在#2
中找到间隔
SELECT Cal1.startDate, Cal2.startDate AS endDate
FROM Cal1 JOIN Cal2
ON Cal2.startDate BETWEEN Cal1.startDate AND Cal1.endDate
UNION ALL
SELECT Cal2.endDate AS startDate, Cal1.endDate
FROM Cal1 JOIN Cal2
ON Cal2.endDate BETWEEN Cal1.startDate AND Cal1.endDate
UNION ALL
SELECT Cal1.startDate, Cal1.endDate
FROM Cal1 LEFT JOIN Cal2
ON Cal2.startDate BETWEEN Cal1.startDate AND Cal1.endDate
OR Cal1.startDate BETWEEN Cal2.startDate AND Cal2.endDate
WHERE Cal2.ID IS NULL
ORDER BY startDate
如何在START和END之间的没有日历中找到间隔:
SELECT starts.d AS startDate, MIN(ends.d) AS endDate
FROM (
SELECT @start AS d
UNION
SELECT Cal1.endDate
FROM Cal1 LEFT JOIN Cal2
ON Cal1.endDate BETWEEN Cal2.startDate AND Cal2.endDate
WHERE Cal1.endDate BETWEEN @start AND @end
AND Cal2.ID IS NULL
UNION
SELECT Cal2.endDate
FROM Cal1 RIGHT JOIN Cal2
ON Cal2.endDate BETWEEN Cal1.startDate AND Cal1.endDate
WHERE Cal2.endDate BETWEEN @start AND @end
AND Cal1.ID IS NULL
) starts JOIN (
SELECT @end AS d
UNION
SELECT Cal1.startDate
FROM Cal1 LEFT JOIN Cal2
ON Cal1.startDate BETWEEN Cal2.startDate AND Cal2.endDate
WHERE Cal1.startDate BETWEEN @start AND @end
AND Cal2.ID IS NULL
UNION
SELECT Cal2.startDate
FROM Cal1 RIGHT JOIN Cal2
ON Cal2.startDate BETWEEN Cal1.startDate AND Cal1.endDate
WHERE Cal2.startDate BETWEEN @start AND @end
AND Cal1.ID IS NULL
) ends ON starts.d < ends.d
GROUP BY startDate
在sqlfiddle上查看。