sql - 查找给定日期范围、持续时间和不可用日期列表的可用公寓

标签 sql ruby postgresql bit-manipulation

我有一个难题,希望有人能帮我解决

我有一张公寓列表。每个列表都有一个或多个“不可用”日期单独存储在另一个表中,我们将其称为“off_days”。例如9 月 1 日至 4 日期间不可用的列表将在“off_days”表中包含 4 个条目,每天一个。

我正在寻找最有效的方法来搜索(最好是在数据库级别)两个日历日之间至少有 N 个连续可用天的列表(“可用”是指不在“off_days”表中的任何一天)特别列出)。例如“显示 9 月份至少有 5 个连续可用天数的所有列表”

我一直在思考如何在现实世界中解决这个问题(通过查看标有 X 的日历并扫描空闲 block ),并开始考虑使用二进制来表示可用/不可用的天数。即对于给定的一周,0111001 ( = 57) 会告诉我该周最多有连续三天可用。

这个question一旦我有了给定日期范围的二进制数,这似乎是一个好的开始,但现在我陷入了如何在给定日期范围动态计算该数字的问题上,再次,在数据库级别......有什么想法吗?或者对这种方法或另一种方法的想法?

最佳答案

公寓可在休息日空档使用。这意味着您想知道每个序列的间隙有多大,lag() 函数可以为您提供以下信息:

select od.*,
       lag(unavailable) over (partition by apartmentid order by unavailable) as prev_una
from offdays od;

实际天数是不可用天数与前一个天数之间的差值减 1。现在,假设两个日历日为 v_StartDatev_EndDate。现在你基本上可以得到你想要的东西:

select od.*,
       ((case when unavailable is NULL or unavailable > v_EndDate
              then v_EndDate + 1 else unavailable
         end) -
        (case when prev_una is null or prev_una < v_StartDate
              then v_StartDate - 1 else prev_una
         end) - 1
       ) as days_available
from (select od.*, lag(unavailable) over (partition by apartmentid order by unavailable) as prev_una
      from offdays od
     ) od
order by days_available desc;

case 逻辑本质上是在句点之前和之后添加停止日期。

这并不完全完整,因为它存在边界问题:当公寓不在休息日时会出现问题,当不可用时段超出范围时会出现问题。让我们用union all和一些过滤来解决这个问题:

select od.*,
       ((case when unavailable is NULL or unavailable > v_EndDate
              then v_EndDate + 1 else unavailable
         end) -
        (case when prev_una is null or prev_una < v_StartDate
              then v_StartDate - 1 else prev_una
         end) - 1
       ) as days_available
from (select od.apartmentId, unavailable,
             lag(unavailable) over (partition by apartmentid order by unavailable) as prev_una
      from offdays od
      where od.unavailable between v_StartDate and v_EndDate
      union all
      select apartmentid, NULL, NULL
      from apartments a
      where not exists (select 1
                        from offdays od
                        where od.apartmentid = a.apartmentid and
                              od.unavailable between v_StartDate and v_EndDate
                       )
     ) od
order by days_available desc;

关于sql - 查找给定日期范围、持续时间和不可用日期列表的可用公寓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25342170/

相关文章:

sql - while 循环遇到符号 > 错误

sql - Rails 选择不同的并按最近的顺序排序

mysql - 用 SQL 证明关系演算

SQL Server 错误 515

ruby - 在 Ruby 问题中包含文件

mysql - 如何通过 Rails 迁移减少存在值的 MySQL 列的 varchar?

sql - 需要一个函数,将总行数除以特定文本的行数

sql - 通过聚合函数中其他列的(第一个值)对不同的列值进行排序

sql - SQL Reporting Services 是否可与 Azure 或任何其他 Azure 新推出的报告服务一起使用?

ruby-on-rails - 搜索栏 + 选择标签栏