简体   繁体   English

MySQL预订可用性,重叠日期范围

[英]MySQL booking availability, overlapping date ranges

I have a table with bookings: 我有一张预订表:

  • id (int) id(int)
  • quantity (tinyint) 数量(tinyint)
  • date_start (timestamp) date_start(时间戳)
  • date_end (timestamp) date_end(时间戳)

Bookings can overlap, so there can for example be 20 bookings at the same time. 预订可以重叠,因此例如可以同时进行20次预订。 Now I want to do two queries: 现在我想做两个查询:

1) Retrieve the maximum sum of quantities within a given period. 1)检索给定时间段内的最大数量总和

2) Retrieve the minimum sum of quantities within a given period. 2)检索给定时期内的最小数量总和

I have no idea how to add the quantities of ONLY the overlapping bookings together, and not of non-overlapping bookings. 我不知道如何将重叠预订的数量加在一起,而不是非重叠预订。 Any help would be greatly appreciated. 任何帮助将不胜感激。

edit: i drew a picture for clarity: http://i.imgur.com/8GDLV.png 编辑:我为了清晰起见画了一幅画: http//i.imgur.com/8GDLV.png

  1. Construct a list of all booking boundaries (ie start and end dates) which occur in the desired period: 构建在期望期间发生的所有预订边界(即开始和结束日期)的列表:

      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. Add to that the boundary which occurs immediately before the desired period: 添加到所需时间段之前的边界:

     -- [ 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. Make an outer join between this result and the bookings table, keeping all of the boundaries but only including a booking if it contributes to the number of simultaneous people after the boundary: 在此结果与bookings表之间建立外部bookings ,保留所有边界,但仅包括预订,如果它有助于边界的同时人数:

     FROM bookings RIGHT JOIN ( -- [ from part 2 above ] ) t ON date_start <= boundary AND boundary < date_end 
  4. Sum the number of people at each boundary: 总结每个边界的人数:

     SELECT IFNULL(SUM(quantity),0) AS simultaneous_people -- [ from part 3 above ] GROUP BY boundary 
  5. Find the maximum and minimum: 找到最大值和最小值:

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

Putting it all together: 把它们放在一起:

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

See it on sqlfiddle . sqlfiddle上看到它。

There is no field for grouping in given data structure in the question. 在问题中的给定数据结构中没有用于分组的字段。 So assuming you are grouping by ID . 所以假设您按ID进行分组。

1). 1)。 To get maximum use MAX 为了最大限度地利用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). 2)。 To get maximum min MIN 获得最大最小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 看到这个SQLFiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM