【问题标题】:Find days with available slots for a specific booking duration查找特定预订期限内有可用时段的日期
【发布时间】:2014-06-23 08:39:56
【问题描述】:

我有一张这样预订的桌子:

+------------+----------+----------+
| date       | time     | duration |
+------------+----------+----------+
| 2014-05-10 | 13:00:00 | 60       |
| 2014-05-13 | 09:00:00 | 60       |
| 2014-05-13 | 10:00:00 | 60       |
| 2014-05-13 | 13:00:00 | 60       |
| 2014-05-13 | 17:00:00 | 60       |
| 2014-05-13 | 18:00:00 | 60       |
| 2014-05-14 | 09:00:00 | 720      |
| 2014-05-15 | 09:00:00 | 60       |
| 2014-05-15 | 11:00:00 | 60       |
| 2014-05-15 | 12:00:00 | 60       |
+------------+----------+----------+

所以,我可以预订一小时或全天的预订。

现在,我想创建一个一小时的新预订,并且我想知道特定月份的哪几天有空闲时间。我不想知道所有空闲时段(就像其他 SO 问题一样),我只想知道什么天可以分配这个预订。 因此,知道了开闭时间、新的预订时长和月份,我需要一个可以返回如下内容的 SQL 查询:

+------------+
| free_days  |
+------------+
| 2014-05-01 |
| ...        |
| 2014-05-08 |
| 2014-05-09 |
| 2014-05-10 |
| 2014-05-11 |
| 2014-05-12 |
| 2014-05-13 |
| 2014-05-15 |
| ...        |
| 2014-05-31 |
+------------+

2014-05-14 缺失,因为有一个全天预订,但如果有 12 个一小时预订,其他日期可能会缺失。

我查看了其他 SO 文章,但无法对其进行调整。有什么想法吗?

【问题讨论】:

  • 我的机器上没有运行数据库,但如果我正确理解了这个问题,SELECT date AS free_days FROM bookings WHERE SUM(duration) < 720 GROUP BY date 之类的东西应该很接近。您希望总预订量低于阈值的天数。
  • 我认为重新设计数据库会帮助您解决这个问题。假设 1 小时槽,创建一个包含所有可用槽的表。包括一个booked_by 列。然后您可以检查预订者为空或具有默认值的记录。
  • 感谢@JohnC,这非常接近,但我将其更改为使用 HAVING 而不是 SUM,因为您不能在 WHERE 中使用 SUM。但是,只有当那一天已经出现在表中时,才会返回有空闲时间的天数。使用我的示例预订表,返回第 10 天、第 13 天和第 15 天。我想要一个月中的所有天,包括那些不在表中并且全天免费的天。我可以在使用 PHP 查询之后添加它,但是完整的 SQL 查询将是完美的。
  • 啊,对。这就是我从头顶上工作得到的。不过,我认为没有任何查询可以产生不在表中的数据。我能想到的最接近的方法是创建一个包含每个日期的表格以加入您的有用表格。如果可行的话,丹的想法也有很大的潜力。您甚至可以创建一个视图来替换原始数据。

标签: mysql sql


【解决方案1】:

我只在Sql server中测试过,虽然我认为应该非常相似:

create table #AllDatesInRange
(
     date datetime
)

declare @maxDate datetime 
declare @currentdate datetime 

set @maxDate = (select max(date) from table_1)
set @currentdate = (select min(date) from table_1)

while @currentdate <= @maxDate
begin 
     insert #AllDatesInRange(date) values(@currentdate)
     set @currentdate = dateadd(day,1,@currentdate)
End 

--missing dates 
 SELECT A.date, 'Free All Day' as [Free slots] from #AllDatesInRange A 
 LEFT JOIN table_1 B ON 
 A.date = B.date 
 WHERE B.date IS NULL 

 UNION All

 select date, 'One or more slots free' as [Free slots] FROM table_1
 group by Date
 having sum(duration) < 720

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多