-2

我正在尝试创建具有多个资源的预订系统:Calendar#1 和 Calendar#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
4

1 回答 1

1
  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
    
  2. 如何获得在 #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
    
  3. 如何在 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上查看它们。

于 2012-12-18T03:26:24.407 回答