2012-08-31 24 views
1

我有預訂的表:MySQL的預訂的可用性,重疊的日期範圍

  • ID(INT)
  • 量(TINYINT)
  • DATE_START(時間戳)
  • DATE_END(時間戳)

預訂可以重疊,因此可以同時預訂20個預訂。現在我想要做兩個查詢:

1)檢索在給定時間內的最大數量總和

2)檢索在給定時間內的最小數量總和

我不知道如何將的數量相加,只將重疊預訂加在一起,而不是非重疊預訂。任何幫助將不勝感激。

編輯:我畫了一幅畫的清晰度:http://i.imgur.com/8GDLV.png

+2

你試過了什麼? –

+0

SUM(數量)'總和數量'MIN'和'MAX'將找到最小值和最大值。查詢將如下所示:'SELECT MAX(SUM(quantity))...' – Leri

+0

我目前使用SELECT * FROM bookings WHERE $ period_start <= date_end AND $ period_end> = date_start檢索一段時間內的所有預訂;然後我使用PHP來瀏覽期間範圍並計算數量。它可以工作,但速度很慢,特別是在日期範圍較大的情況下。 –

回答

2
  1. 構建所有預訂邊界的列表(即就發生在所期望的時間段的結束日期):

    SELECT date_start AS boundary 
        FROM bookings 
        WHERE date_start BETWEEN @start AND @end 
    UNION 
        SELECT date_end 
        FROM bookings 
        WHERE date_end BETWEEN @start AND @end 
    
  2. 添加到該所期望的時間段之前立即發生的邊界:

    -- [ from part 1 above ] 
    UNION 
        SELECT MAX(boundary) 
        FROM (
        SELECT MAX(date_start) AS boundary 
        FROM bookings 
        WHERE date_start <= @start 
        UNION ALL 
        SELECT MAX(date_end) 
        FROM bookings 
        WHERE date_end <= @end 
    ) t 
    
  3. 使外這個結果和之間的連接bookings表,保持所有的界限,但只有包括預訂,如果它有助於人們同步的後的邊界:

    FROM bookings RIGHT JOIN (
        -- [ from part 2 above ] 
    ) t ON date_start <= boundary AND boundary < date_end 
    
  4. 點心的人在每個邊界數量:

    SELECT IFNULL(SUM(quantity),0) AS simultaneous_people 
    -- [ from part 3 above ] 
    GROUP BY boundary 
    
  5. 找出最大和最小:

    SELECT MIN(simultaneous_people), 
         MAX(simultaneous_people) 
    FROM (
        -- [ from part 4 above ] 
    ) t 
    

全部放在一起:

SELECT MIN(simultaneous_people), 
     MAX(simultaneous_people) 
FROM (
    SELECT IFNULL(SUM(quantity),0) AS simultaneous_people 
    FROM bookings RIGHT JOIN (
    SELECT date_start AS boundary 
    FROM bookings 
    WHERE date_start BETWEEN @start AND @end 
    UNION 
    SELECT date_end 
    FROM bookings 
    WHERE date_end BETWEEN @start AND @end 
    UNION 
    SELECT MAX(boundary) 
    FROM (
     SELECT MAX(date_start) AS boundary 
     FROM bookings 
     WHERE date_start <= @start 
    UNION ALL 
     SELECT MAX(date_end) 
     FROM bookings 
     WHERE date_end <= @end 
    ) t 
) t ON date_start <= boundary AND boundary < date_end 
    GROUP BY boundary 
) t 

請參閱sqlfiddle

+0

哇,太棒了。正是我需要的,它完美的工作!非常感謝你的幫助,我會研究你的解決方案,直到我完全理解它。 –

+0

當查詢重疊結尾的時間範圍時,我遇到了問題 - 例如,小提琴中的7.2-8。看起來,將「聯盟 SELECT @start UNION SELECT @end」添加到聯合堆棧解決了這個問題,因爲它強制考慮可能通過「邊界」選擇的裂縫落下的東西。 –

1

沒有在問題中給出的數據結構的分組沒有現場。所以假設你正在分組ID

1)。獲得最大限度的使用MAX

SELECT MAX(TotalQty) FROM 
(
    SELECT SUM(Quantity) AS TotalQty FROM Bookings 
    WHERE date_End<='<To Date>' 
    AND date_Start>='<From Date>' 
    GROUP BY id 
) SumQty 

2)。爲了獲得最大的分MIN

SELECT MIN(TotalQty) FROM 
(
    SELECT SUM(Quantity) AS TotalQty FROM Bookings 
    WHERE date_End<='<To Date>' 
    AND date_Start>='<From Date>' 
    GROUP BY id 
) SumQty 

See this SQLFiddle