0

我有一个函数,我想计算两个日期之间的秒数,这些秒数应该只在我们公司的营业时间内计算。因为完成任务可能需要几天时间,所以我创建了一个 while 循环,应该增加天数

这是我的循环:

    WHILE TO_DATE(TRUNC(dateIterator),'YYYY-MM-DD') < TO_DATE(TRUNC(CallbackUpdatedDate),'YYYY-MM-DD') LOOP
 calculateIntervalFrom := null;
calculateIntervalTo := null;

SELECT THIS_DATE_OPENING,
 THIS_DATE_CLOSING,
 NEXT_DATE_OPENING
INTO thisDateOpening, thisDateClosing, nextDay
FROM KS_DRIFT.SYS_DATE_KS
WHERE THIS_DATE = dateIterator;

-- gets calculated from
calculateIntervalFrom := thisDateOpening;

-- Gets calculateTo
IF dateIterator = TO_DATE(TRUNC(CallbackUpdatedDate),'YYYY-MM-DD') THEN
calculateIntervalTo := CallbackUpdatedDate;
ELSE
calculateIntervalTo := thisDateClosing;
END IF;
fromSeconds := abs(extract(second from TO_TIMESTAMP(calculateIntervalFrom))) + extract(minute from TO_TIMESTAMP(calculateIntervalFrom)) * 60 + extract(hour from TO_TIMESTAMP(calculateIntervalFrom)) * 60 * 60;
toSeconds :=abs(extract(second from TO_TIMESTAMP(calculateIntervalTo))) + extract(minute from TO_TIMESTAMP(calculateIntervalTo)) * 60 + extract(hour from TO_TIMESTAMP(calculateIntervalTo)) * 60 * 60;
intervalDifference := fromSeconds - toSeconds;

solvedSeconds := solvedSeconds + intervalDifference;
dateIterator := nextDay;
dbms_output.put_line(nextDay);

一个小小的解释

所以想法是只要值dateIterator(即创建行的日期)与上次更新行的时间不同(CallbackUpdatedDate),它将从表中选择今天和接下来的几天营业时间KS_DRIFT.SYS_DATE_KS

如果今天的日期与它相同,CallbackUpdatedDate它将设置calculateIntervalTo等于,CallbackUpdatedDate否则它会将值设置为thisDateClosing

然后它将计算两个日期之间的秒数并将它们添加到NUMBER solvedSeconds

之后我会设置dateIterator为下一个开放日:dateIterator := nextDay;

这有效,但只有两次,然后它只是结束循环:

这是它尝试计算的两个日期:

创建时间:2013-03-26 10:23:33

最后更新时间:2013-04-03 09:25:10

dbms_output.put_line(nextDay); outputs these two values: 

2013-03-27 和 2013-03-27

从表面上看,while 循环中的 SELECT 语句似乎没有按预期工作,但我根本不明白为什么?

4

2 回答 2

2

您如何处理日期看起来很奇怪:

TO_DATE(TRUNC(dateIterator),'YYYY-MM-DD') 

所以 dateIterator 是您截断的日期,即您删除时间部分。这为您提供了一个时间设置为 00:00:00 的日期。但是随后您在该日期使用 to_date 函数,就好像它是一个字符串一样。这在我看来是错误的。

然后在你的选择语句中你有

WHERE THIS_DATE = dateIterator

我想知道:上面你必须从 dateIterator 中删除时间。在这里你没有。您的表是否有包含时间部分的 dateIterator 条目?

我希望这些发现已经有助于解决问题。

于 2013-04-11T14:56:43.153 回答
1

与其使用 WHILE 循环,不如只使用一个查询?就像是:

select (end_date - start_date - 
        (select coalesce(sum(least(NEXT_DATE_OPENING,end_date) -
                             greatest(THIS_DATE_CLOSING,start_date)),0)
         from KS_DRIFT.SYS_DATE_KS
         where THIS_DATE_CLOSING < end_date and 
               NEXT_DATE_OPENING > start_date)) * 86400 available_time
from dual

SQLFiddle在这里

于 2013-04-11T14:55:10.593 回答