获取日期时间范围内的教室可用时间

2023-12-12

我正在使用 Oracle 11g,我遇到了这个问题。我还想不出任何想法来解决它。

我有一张桌子,教室里有人。我需要找到的是日期时间范围之间的可用小时数。例如,我有A、B、C房间,占用教室表如下:

Classroom        start                 end  
   A         10/10/2013 10:00      10/10/2013 11:30  
   B         10/10/2013 09:15      10/10/2013 10:45  
   B         10/10/2013 14:30      10/10/2013 16:00  

我需要得到的是这样的:

with date time range between '10/10/2013 07:00' and '10/10/2013 21:15'

Classroom    avalailable_from        available_to  
   A         10/10/2013 07:00      10/10/2013 10:00  
   A         10/10/2013 11:30      10/10/2013 21:15  
   B         10/10/2013 07:00      10/10/2013 09:15  
   B         10/10/2013 10:45      10/10/2013 14:30  
   B         10/10/2013 16:00      10/10/2013 21:15  
   C         10/10/2013 07:00      10/10/2013 21:15  

有没有办法可以用 sql 或 pl/sql 来实现这一点?


我正在寻找一个在概念上至少与 Wernfried 类似的解决方案,但我认为它也足够不同,可以发布。开始是相同的想法,首先生成可能的时间段,并假设您正在查看 15 分钟的窗口:我使用 CTE 是因为我认为它们比嵌套选择更清晰,尤其是在这么多级别的情况下。

with date_time_range as (
  select to_date('10/10/2013 07:00', 'DD/MM/YYYY HH24:MI') as date_start,
    to_date('10/10/2013 21:15', 'DD/MM/YYYY HH24:MI') as date_end
  from dual
),
time_slots as (
  select level as slot_num,
    dtr.date_start + (level - 1) * interval '15' minute as slot_start,
    dtr.date_start + level * interval '15' minute as slot_end
  from date_time_range dtr
  connect by level <= (dtr.date_end - dtr.date_start) * (24 * 4) -- 15-minutes
)
select * from time_slots;

这将为您提供指定的开始日期和结束日期之间的 57 个 15 分钟时段。 CTE 为date_time_range并不是绝对必要的,您可以将日期直接放入time_slots条件,但您必须重复它们,然后引入可能的故障点(并且意味着从 JDBC 或其他地方多次绑定相同的值)。

然后,这些槽位可以交叉连接到教室列表,我假设该列表已经在另一个表中,这将为您提供 171 (3x57) 种组合;这些可以与现有预订进行比较 - 一旦这些预订被消除,您就剩下 153 个没有预订的 15 分钟时段。

with date_time_range as (...),
time_slots as (...),
free_slots as (
  select c.classroom, ts.slot_num, ts.slot_start, ts.slot_end,
    lag(ts.slot_end) over (partition by c.classroom order by ts.slot_num)
      as lag_end,
    lead(ts.slot_start) over (partition by c.classroom order by ts.slot_num)
      as lead_start
  from time_slots ts
  cross join classrooms c
  left join occupied_classrooms oc on oc.classroom = c.classroom
    and not (oc.occupied_end <= ts.slot_start 
      or oc.occupied_start >= ts.slot_end)
  where oc.classroom is null
)
select * from free_slots;

但随后你必须将它们折叠成连续的范围。有多种方法可以做到这一点;在这里,我查看前一行和下一行来确定特定值是否是范围的边缘:

with date_time_range as (...),
time_slots as (...),
free_slots as (...),
free_slots_extended as (
  select fs.classroom, fs.slot_num,
    case when fs.lag_end is null or fs.lag_end != fs.slot_start
      then fs.slot_start end as slot_start,
    case when fs.lead_start is null or fs.lead_start != fs.slot_end
      then fs.slot_end end as slot_end
  from free_slots fs
)
select * from free_slots_extended
where (fse.slot_start is not null or fse.slot_end is not null);

现在我们减少到 12 行。 (外where子句消除了上一步中 153 个槽位中的所有 141 个槽位,因为我们只关心边缘):

CLASSROOM   SLOT_NUM SLOT_START       SLOT_END       
--------- ---------- ---------------- ----------------
A                  1 2013-10-10 07:00                  
A                 12                  2013-10-10 10:00 
A                 19 2013-10-10 11:30                  
A                 57                  2013-10-10 21:15 
B                  1 2013-10-10 07:00                  
B                  9                  2013-10-10 09:15 
B                 16 2013-10-10 10:45                  
B                 30                  2013-10-10 14:30 
B                 37 2013-10-10 16:00                  
B                 57                  2013-10-10 21:15 
C                  1 2013-10-10 07:00                  
C                 57                  2013-10-10 21:15 

因此,这些代表边缘,但位于不同的行上,最后一步将它们组合起来:

...
select distinct fse.classroom,
  nvl(fse.slot_start, lag(fse.slot_start)
    over (partition by fse.classroom order by fse.slot_num)) as slot_start,
  nvl(fse.slot_end, lead(fse.slot_end)
    over (partition by fse.classroom order by fse.slot_num)) as slot_end
from free_slots_extended fse
where (fse.slot_start is not null or fse.slot_end is not null)

或者将所有这些放在一起:

with date_time_range as (
  select to_date('10/10/2013 07:00', 'DD/MM/YYYY HH24:MI') as date_start,
    to_date('10/10/2013 21:15', 'DD/MM/YYYY HH24:MI') as date_end
  from dual
),
time_slots as (
  select level as slot_num,
    dtr.date_start + (level - 1) * interval '15' minute as slot_start,
    dtr.date_start + level * interval '15' minute as slot_end
  from date_time_range dtr
  connect by level <= (dtr.date_end - dtr.date_start) * (24 * 4) -- 15-minutes
),
free_slots as (
  select c.classroom, ts.slot_num, ts.slot_start, ts.slot_end,
    lag(ts.slot_end) over (partition by c.classroom order by ts.slot_num)
      as lag_end,
    lead(ts.slot_start) over (partition by c.classroom order by ts.slot_num)
      as lead_start
  from time_slots ts
  cross join classrooms c
  left join occupied_classrooms oc on oc.classroom = c.classroom
    and not (oc.occupied_end <= ts.slot_start
      or oc.occupied_start >= ts.slot_end)
  where oc.classroom is null
),
free_slots_extended as (
  select fs.classroom, fs.slot_num,
    case when fs.lag_end is null or fs.lag_end != fs.slot_start
      then fs.slot_start end as slot_start,
    case when fs.lead_start is null or fs.lead_start != fs.slot_end
      then fs.slot_end end as slot_end
  from free_slots fs
)
select distinct fse.classroom,
  nvl(fse.slot_start, lag(fse.slot_start)
    over (partition by fse.classroom order by fse.slot_num)) as slot_start,
  nvl(fse.slot_end, lead(fse.slot_end)
    over (partition by fse.classroom order by fse.slot_num)) as slot_end
from free_slots_extended fse
where (fse.slot_start is not null or fse.slot_end is not null)
order by 1, 2;

这使:

CLASSROOM SLOT_START       SLOT_END       
--------- ---------------- ----------------
A         2013-10-10 07:00 2013-10-10 10:00 
A         2013-10-10 11:30 2013-10-10 21:15 
B         2013-10-10 07:00 2013-10-10 09:15 
B         2013-10-10 10:45 2013-10-10 14:30 
B         2013-10-10 16:00 2013-10-10 21:15 
C         2013-10-10 07:00 2013-10-10 21:15 

SQL小提琴.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

获取日期时间范围内的教室可用时间 的相关文章

  • 出现错误:字符串未被识别为 C# 中的有效日期时间

    出现如下错误 mscorlib dll 中发生类型为 System FormatException 的未处理异常附加信息 字符串未被识别为有效的日期时间 我正在使用这段代码 string datetime DateTime Parse en
  • “$$ 处或附近的未终止的美元引号字符串

    我试图使用 DBeaver 声明一些变量并不断遇到此错误 Unterminated dollar quoted string at or near DO DECLARE A integer B integer BEGIN END 有任何想法
  • 将子查询的结果插入表中并带有常量

    相关表格的概要如下 我有一个表 我们称之为联接 它有两列 都是其他表的外键 我们将这两列称为 userid 和buildingid 因此 join 看起来像 join userid buildingid 我基本上需要在这个表中插入一堆行 通
  • MySQL如何根据字段是否存在来插入新记录或更新字段?

    我正在尝试实现一个评级系统 在数据库表中保留以下两个字段 评级 当前评级 num rates 迄今为止提交的评分数量 UPDATE mytable SET rating rating num rates theRating num rate
  • 如何通过Object Id和Column Id查询表数据?

    有桌子Clients PK LastName Name Address 1 Vidal Arturo St 2 Lavezzi Ezequiel St 3 Cuadrado Guillermo St 我想得到 通过以下查询 我可以得到前四列
  • Sql 查询:Sum,表中所有可能的行组合

    SQL Server 2008 R2 表结构示例 create table TempTable ID int identity value int insert into TempTable values 6 insert into Tem
  • 混合语言源目录布局

    我们正在运行一个使用多种不同语言的大型项目 Java Python PHP SQL 和 Perl 到目前为止 人们一直在自己的私有存储库中工作 但现在我们希望将整个项目合并到一个存储库中 现在的问题是 目录结构应该是什么样的 我们应该为每种
  • 如何登录Oracle数据库?

    我对 Oracle 数据库中常用的日志记录方法感兴趣 我们的方法如下 我们为要记录的表创建一个日志表 日志表包含原始表的所有列以及一些特殊字段 包括时间戳 修改类型 插入 更新 删除 修改者的 id 原始表上的触发器为每次插入和删除创建一个
  • MySQL中是否有类似Oracle中“level”的函数[重复]

    这个问题在这里已经有答案了 我面临一个场景 如果输入是 10 我想要一个数字序列 1 2 3 10 在甲骨文中levelfunction 提供了该功能 我想知道如何在 MySQL 中执行相同的任务 谢谢 您可以在 mysql 中使用此查询
  • 如何从 Python 中的日期时间对象计算年份分数?

    我有两个日期表示为datetime对象并尝试计算两个日期之间的时间 以年的分数为单位 相当于 Excelyearfrac功能 Using relativedelta我可以得到年数 月数和日期之间的天数 但不能得到年的分数 我也可以减去日期来
  • .NET 中的 new Date().getTime()

    基本上我想在 NET 中执行以下操作 但我不知道如何操作 var d new Date getTime milliseconds since 1970 01 01 我不太确定您是否可以在 NET 中获取 UNIX 日期 但您有 DateTi
  • MySQL:你能指定一个随机限制吗?

    有没有办法在 SQL MySQL 中随机化限制数字 我希望能够做的是在查询中获取随机数量的结果以在插入子查询中使用 而无需任何服务器端脚本 我希望能够作为假设说明运行的查询是 SELECT id FROM users ORDER BY RA
  • 以无法破坏的方式限制表中允许的记录数量

    我们有一个 Web 应用程序 Grails 我们将根据用户数量为其出售许可证 数据库 Oracle 10g 中有一个表保存用户 客户将托管自己的软件和数据库副本 有人可以建议一些策略来限制允许存在于用户表中的记录数量 从而使客户无法合理地破
  • Postgresql 中的 id 列位置重要吗?

    我正在测试删除主键列 id 的迁移 我想使用外键作为主键 当我运行并恢复迁移时 我看到表的状态是相同的 只是 id 列现在是最后一个 它会以任何方式改变我的数据库的行为吗 我是否应该费心去恢复迁移恢复代码中的列顺序 理论上一切都应该没问题
  • 使用绑定和空值命中 Oracle 索引的最佳查询

    我有一个表 该表在多个列上有一个索引 其中许多列可以为空 CREATE UNIQUE INDEX UX MYTABLE A B C D E ON MYTABLE A B C D E 现在 我在 C 代码中尝试检查该表并精确命中索引 对于每个
  • (SQL) 识别字段中字符串格式多次出现的位置

    我需要将叙述字段 自由文本 拆分为多行 目前的格式如下 Case Reference Narrative XXXX XX 123456 Endless Text up to 50k characters 在作为文本的叙述字段中 各个条目 当
  • 具有 LINQ 支持的最完整的 ORM?

    我正在寻找一个提供完整或接近完整的 LINQ 支持的 ORM LINQ 到 SQL 支持 LINQ 内部的所有内容 Contains Math Log 等 在不创建新数据上下文的情况下无法预先加载关系属性 ADO NET 实体框架 糟糕的
  • SQL Server PIVOT 函数

    我有一个检索所有代理及其模块的查询 结果集将每个模块返回 1 行 SELECT am agentID AS agentid pa agentDisplayName agentdisplayname m ModuleName ModuleNa
  • 如何检测 Postgres 中持有锁的查询?

    我想不断跟踪 postgres 中的互锁 我碰到锁具监控 https wiki postgresql org wiki Lock Monitoring文章并尝试运行以下查询 SELECT bl pid AS blocked pid a us
  • 如何打印Oracle中过程的定义?

    oracle中有没有办法查看过程的结构是什么 我正在尝试记录并运行程序 并希望将实际的程序结构存储在我的日志中 您可以查询ALL SOURCE table SELECT text FROM all source WHERE owner lt

随机推荐

  • 这是在 java 中将 FocusListener 添加到 JTextFields 的正确方法吗?

    我有数百个JTextFields在我的 Java 应用程序中 我想添加FocusListener对所有这些设置水平对齐方式的文本和添加焦点监听器在每个文本字段上 所以 我做了这个方法 而且效果很好 但我只是想知道这种方法是否正确 或者有什么
  • 使用 sed 的追加/更改/插入而不带换行符

    我想替换 SED 中的模式空间 我可以这样做s hello world 但我可以使用c以某种方式命令 在我的 sed 脚本中不使用换行符 我并不完全清楚这是否可能 同样的问题a and i命令 如果你的 shell 是 bash 这里有一个
  • Rails:调用“id”主键方法时出现“堆栈级别太深”错误

    这是转发于另一个问题 这次隔离比较好 在我的environment rb 文件中 我更改了这一行 config time zone UTC 到这一行 config active record default timezone utc 于是乎
  • 如何在导航抽屉中的两个片段之间通信数据

    我有一个导航抽屉 其中包含不同的片段 每个项目显示一个片段 我想将数据从一个片段传递到另一个片段 我只有一个包含导航抽屉的活动 其中有一个片段列表 我尝试了很多解决方案 捆绑和意图 但我无法解决我的问题 任何人都可以帮我吗 这是我的第一个片
  • 如何在 Windows Phone 7 中使用 BinaryFormatter

    如何在 Windows Phone 7 中使用 BinaryFormatter 我用这个using System Runtime Serialization Formatters Binary在 service1 svc cs 中 但我无法
  • 使用 Windows 批处理文件从 txt 文件中仅读取 x 行

    如何从 a txt 文件中只读取 X 行 该文件包含目录的所有名称 我只想读取 x 行 X 可以是 1 到 99 之间的数字 您需要根据需要修改此设置 但下面的脚本将循环遍历文件 directories txt 并回显该行的内容 直到达到中
  • Java 中什么会引发 IOException?

    java io IOException似乎是最常见的异常类型 巧合的是 它似乎也是最模糊的 我不断看到throws IOException每当使用套接字 文件等进行编写时 我实际上从未被触发过 所以我想知道应该触发异常的是什么 该文档对于解
  • 不同实体值具有相同同义词的对话流歧义

    我在使用对话流 api ai 开发代理时遇到问题 我使用了很多彼此不同的实体值 然而 某些实体值有类似的同义词 但代理仅返回一个值 我怎样才能获得所有可能的匹配或提出问题来解决歧义 例如我有一个意图 告诉我 ABC 特快列车的位置 if m
  • Java Spring + Jersey 子资源:在运行时注入构造函数参数

    我定义了以下方法 返回一个表示子资源定位器 泽西岛 的 bean Path slug public PageResource page PathParam slug String siteSlug throws AppException s
  • 如何禁止用户在 Groovy 脚本中做坏事?

    我计划将 Groovy 脚本引擎集成到我的游戏中 这样它将为游戏提供良好的可修改性 但是如何防止玩家编写邪恶的脚本 例如删除 C 驱动器上的所有文件 Groovy 包括类似库java io File默认情况下 因此一旦他们决定编写此类脚本
  • Swift - 如何检测方向变化

    我想将两个图像添加到单个图像视图 即横向一个图像和纵向另一个图像 但我不知道如何使用快速语言检测方向变化 我尝试过这个答案 但它只需要一张图片 override func viewWillTransitionToSize size CGSi
  • 如何在 Java 中使用密码保护压缩的 Excel 文件?

    我有一个关于保护 Excel 文件的密码的问题 情况是 我有一个 zip 文件 其中有一个 Excel 文件 我需要编写一个Java程序 以密码保护Excel文件 因此 用户应该能够解压缩该文件 zip 文件不需要受密码保护 但是 Exce
  • 如何在没有 EULA 的情况下启动 ChromeDriver.exe?

    我正在学习使用 Selenium v2 20 以领先于我们的一些程序员 他们很快将用它创建一些浏览器测试 我想在陷阱出现之前发现它们 而我无意中发现了一个 当我创建 ChromeDriver 时 它总是会弹出 Google Chrome E
  • 在 AS3 中从库加载和卸载内容

    我正在做一个 Flash 项目 但我对 ActionScript 很陌生 我在主页上有一个菜单 我想在单击菜单项时显示其他页面 我知道如何从库加载影片剪辑 但我不知道如何指定它们在屏幕上的位置以及如何使它们出现在特定层中 当我点击菜单的另一
  • 如果我们启用僵尸对象,所有弱引用都会被清空吗?

    通常 如果一个对象被释放 所有弱引用都将被清空 如果我们启用僵尸对象会怎么样 产品 gt 编辑方案 gt 启用僵尸对象 弱引用也会被置零吗 否则 在启用僵尸对象时会出现正常情况下不会发生的错误 正如其中一个答案所说 我强烈怀疑弱引用将被消除
  • 如何将秒转换为小时、分钟和秒?

    我有一个以秒为单位返回信息的函数 但我需要以小时 分钟 秒的形式存储该信息 有没有一种简单的方法可以在Python中将秒转换为这种格式 您可以使用datetime timedelta功能 gt gt gt import datetime g
  • 如何让 PHP 在出现错误时生成回溯?

    尝试使用 PHP 的默认仅当前行错误消息来调试 PHP 是可怕的 当产生错误时 如何让 PHP 产生回溯 堆栈跟踪 我的用于安装生成回溯的错误处理程序的脚本
  • 加载 jasperreports 的 .jrxml 文件

    在我的项目中 我将 jrxml 文件存储在名为 com bio ofm mnu views reports jasperReports 的包中 当我尝试加载 jrxml 时出现以下错误 net sf jasperreports engine
  • 将外部 SVG 文件加载到变量中并附加到 html

    我正在尝试用该 SVG 的内容替换嵌入 IMG 标签中的 SVG 图像 并将其内联输出 换句话说 将给定 IMG SRC 属性的 SVG 文件内容加载到变量中 并将其作为内联 SVG 注入 HTML 如下所示 else if type ty
  • 获取日期时间范围内的教室可用时间

    我正在使用 Oracle 11g 我遇到了这个问题 我还想不出任何想法来解决它 我有一张桌子 教室里有人 我需要找到的是日期时间范围之间的可用小时数 例如 我有A B C房间 占用教室表如下 Classroom start end A 10