PL / SQL:我应该使用集合还是进行多个查询?

时间:2013-07-31 12:22:36

标签: sql performance oracle collections plsql

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

某个房间的桌子示例:

enter image description here

(不要介意不同的颜色)

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

(2013年7月31日 - 07-31-2014,00:00-23:59,周一,周二和周五)

我担心的是要构建我的html表的每个方块,我需要进行查询以检查是否定义了特定的时间段。 (例如,如果用户希望从一个房间的10:00到14:00看到整整一周,那么将会以15分钟的间隔建立112个查询表。更不用说用户最多可以看到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个subquerys来检查是否允许用户在这个房间预订......

1 个答案:

答案 0 :(得分:3)

执行此类操作的一种解决方案是创建称为维度的表。您的数组有两个维度,因此您可以创建两个表,例如一个名为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