-2

複数のリソース(Calendar#1とCalendar#2)を使用して予約システムを作成しようとしています。カレンダーには、重複する範囲自体は含まれていません。1つのカレンダーの範囲は、他のカレンダーの複数の範囲にまたがることができます。

以下または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 に答える