【问题标题】:PL/SQL : Should i use a collection or do multiple querys?PL/SQL:我应该使用集合还是执行多个查询?
【发布时间】:2013-07-31 23:22:59
【问题描述】:

我正在做这个项目,我需要创建一个大的 HTML 表格,其中每个表格行是 15 分钟的间隔,每个表格列是一天。目标是在房间可用和不可用时向用户显示想要预订房间的用户。所有网页都是打印出正确 HTML 的 PL/SQL 包。

某个房间的桌子示例:

(不要介意不同的颜色)

所有房间定义都存储在一个包含开始日期、结束日期、开始时间、结束时间和星期几的 Oracle 数据库中。例如,一个定义可以是:

(07-31-2013 - 07-31-2014, 00:00 - 23:59, Mondays,Tuesdays and Fridays)

我担心的是,要构建我的 html 表的每个正方形,我需要进行查询以检查是否定义了该特定时期。 (例如,如果用户想查看一个房间从 10:00 到 14:00 的整周,则将进行 112 次查询以每隔 15 分钟构建表)更不用说用户最多可以查看 4 周并且从任何时间间隔(可能是从 00:00 到 23:59)。另一个问题是我需要检查房间定义,但我还必须多次检查以查看该时间间隔是否被预订占用......所以只需要一周查看 224 次查询。

我的解决方案是获取所有可能影响用户希望查看的时间段的房间定义和预订,并将它们放入一个集合中(1 个集合用于定义,1 个用于预订)。之后,我在这些集合上运行所有测试而不进行查询。我的主过程调用了一个函数,将两个集合作为参数发送,函数返回 true 或 false。

我想知道 oracle 是否可以处理这么多小请求,还是我对集合做了正确的事情?

我读过很多帖子说集合对记忆不好,我担心通过函数参数传递它们可能也无济于事......尽管它可能不适用于我的情况,考虑到集合可能永远不会有更多其中有 1-5 条记录。

我要检查它是否可用的查询是这样的:

SELECT DISTINCT 'Y' 
FROM room_defenition
WHERE
START_DATE <= USER_DATE AND 
END_DATE >= USER_DATE AND
--F_TO_DAY converts the date to the coresponding code
REGEXP_INSTR(MON||TUE||WED||THU||FRI||SAT||SUN,F_TO_DAY(USER_DATE)) <> 0 AND
START_TIME <= USER_START_TIME AND 
END_TIME >= USER_END_TIME;

USER_DATE 将是我正在测试的当前列,而 USER_START_TIME 和 USER_END_TIME 将是当前间隔的两个边界。 (例如 07-31-2013 - 10:00 - 10:15)。

我在 where 子句中还有 2 个子查询来检查是否允许用户在这个房间进行预订...

【问题讨论】:

  • 我不会在这里提供太多帮助,但是您的查询是什么样的?
  • 添加了如果我不使用集合我的查询将如何

标签: sql performance oracle collections plsql


【解决方案1】:

做这类事情的一个解决方案是创建称为维度的表。您的数组有两个维度,因此您将创建两个表,例如一个名为 QUARTERS 的表,每天每 15 分钟有一行(所以 96 行)

id    timestart   timeend
-----------------
1      00:00  00:15
2      00:15  00:30
...

还有一个叫 CALENDAR 的人可以保存全年的天数(或者接下来的 10 年,没关系)

id    dateofday
---------------
1     01/01/2013
2     02/01/2013
...

很容易构建一个查询,它为数组的每个单元格精确地提供一行,无论是否有可用房间。

select timestart, timeend, dateofday
from quarters cross join calendar -- a legitimate use for cross join
where timestart >= user_time_start and
      timeend   <= user_time_end and
      dateofday between user_date_start and user_date_end 
order by quarters.id, calendar.id

结果按数组的行排序,然后按列排序。因此,您可以一次读取一行查询的结果并即时构建您的数组(无需收集或复杂的算法)

现在您只需要添加一个子查询来告诉您房间是否可用,例如:

select timestart, timeend, dateofday,
    (*subquery on room_definition *) available
    from quarters cross join calendar -- a legitimate use for cross join
    where timestart >= user_time_start and
          timeend   <= user_time_end and
          dateofday between user_date_start and user_date_end 
    order by quarters.id, calendar.id

【讨论】:

  • 我想我理解您的概念,但在这种情况下,这不会破坏不进行一堆查询或子查询的目的吗?如果我错了,请纠正我,但是“(*房间定义上的子查询 *)”不会被评估的次数与我的 HTML 表中的正方形一样多吗?
  • 我真的不知道 Oracle 将如何运行子查询,你必须运行一个解释计划。但是所有的数据都将在 Oracle 中被读取、准备和排序,这是它的构建目标并且做得很好。此外,您还消除了准备查询、打开游标、读取结果、关闭游标的开销......
  • +1 虽然我可能会考虑使用外连接到 room_definition 而不是选择子句 - 但这取决于。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
相关资源
最近更新 更多