计算Oracle中给定基准(以周为单位)的剩余时间

时间:2011-11-15 00:32:44

标签: sql oracle elapsedtime

以下是我要做的事情:我有一些数据代表了学生应该通过给定基准(在这种情况下,6月15日)达到的目标。我正在查看一个事务表并运行一些汇总查询,这些查询试图找出在给定时间点有多少学生“在轨道上”,使用“填补数据空白”和“填补空白”中描述的技术库存表'用于计算运行/累计总数并加密数据。 http://download.oracle.com/docs/cd/B28359_01/server.111/b28313/analysis.htm#i1014934

为了表达学生在表格中每一行的“目标进展”,我试图逐步计算到6月15日之前的剩余时间,允许我将运行总数与按比例进行比较目标的版本。

我的数据如下:

Measure    Goal     Year    Week    Date (YYYY-WW)
106141     400000   2011    42      2011-42
128886     400000   2011    43      2011-43
145449     400000   2011    44      2011-44
156921     400000   2011    45      2011-45

我有一个解决方法,但它确实很糟糕和可怕。

,case 
   when year = 2012 then  24 - week
   when year = 2011 then (52 - week) + 24
   else null
 end as weeks_to_june_15

(6月15日是2012年的第24周)。是否有更优雅的甚至是非常正确的方法来做到这一点?每次我使用日期函数尝试计算时,我都会得到非法的数字或文字与格式字符串错误不匹配。

似乎有人完成了与我在这里尝试做的事情有些相关的事情:https://forums.oracle.com/forums/thread.jspa?threadID=633028 但是我不确定使用IYYY和IW重建那个日期是否会让我到达我想去的地方。

使用Oracle 11gR2 Express并希望在数据库中执行,如果可能的话。

谢谢!

2 个答案:

答案 0 :(得分:1)

这很大程度上取决于你对一周的定义。 IWIYYY格式使用ISO标准,该标准规定一周始终在星期一开始并持续7天。这意味着,根据标准,2011年1月1日是2010年第52周的一部分。如果这对您不起作用,那么您需要首先准确定义一周的意思。

由于ISO标准定义明确,因此您可以将一周的第一天视为与周本身等效,这样您就可以准确地使用日期数学。下面是一个功能就是这样。您也可以在SQL中完成所有操作,但PL / SQL使这类事情变得更简单易读。

CREATE OR REPLACE FUNCTION week_diff(p_year NUMBER, 
                                     p_week NUMBER, 
                                     p_end_date DATE)
   RETURN NUMBER AS
   v_end_date   DATE;
   v_start_date DATE;
   v_weeks      NUMBER;
   v_last_week  DATE;
BEGIN
   v_end_date     := TRUNC(TO_DATE(p_end_date, 'mm/dd/yyyy'), 'IW');
   v_start_date   := TRUNC(TO_DATE('2/1/' || p_year, 'mm/dd/yyyy'), 'IYYY') 
                     + (p_week * 7);

   IF TRUNC(v_end_date, 'IYYY') = TRUNC(v_start_date, 'IYYY') THEN
      v_weeks   := (v_end_date - v_start_date) / 7;
   ELSE
      v_last_week   := TRUNC(TO_DATE('12/31/' || TO_CHAR(v_start_date, 'yyyy'),
                                     'mm/dd/yyyy'), 'IW');
      v_weeks       := (v_last_week - v_start_date) / 7 
                       + TO_NUMBER(TO_DATE(v_end_date, 'IW'));
   END IF;

   RETURN v_weeks;
END week_diff;

答案 1 :(得分:0)

trunc (to_date('15-jun-2012') - sysdate)

将为您提供从现在到明年6月15日之间的日历天数。

这应该让你开始。

如果您有一个存储的日期/时间数据项,则表达式为:

trunc (stored,'DAY') 

在前一个星期日产生午夜(见http://www.techonthenet.com/oracle/functions/trunc_date.php),例如,

select count(*) events_per_week, 
       trunc(event_time,'DAY') week_starting
  from event
 group by trunc(event_time,'DAY')

会告诉您每周在事件表中有多少事件。这是一种逐周汇总数据的有效方式,因为它适用于短期和多年的时间段。

如果您的商家规则要求您的星期一星期一开始,请改为执行此操作。

1+trunc(stored-1,'DAY')

如果您想要一个类似'2011-43'的日期/时间数据项,那么

TO_DATE( '2011-43', 'YYYY-WW')

TO_DATE( '2011-43', 'YYYY-IW')

取决于您是否使用ISO周数。见http://www.techonthenet.com/oracle/functions/to_date.php

我更喜欢周日午夜识别一周的方式;它非常直观(“2011年11月13日开始的一周”),并以直截了当的方式处理年终翻转。