【问题标题】:Calculating remaining time to a given benchmark (in weeks) in Oracle计算Oracle中给定基准的剩余时间(以周为单位)
【发布时间】:2011-11-15 00:32:44
【问题描述】:

以下是我要做的事情:我有一些数据代表学生应该通过给定基准(在本例中为 6 月 15 日)达到的目标。我正在查看一个事务表并运行一些汇总查询,试图找出在给定时间点有多少学生“在轨道上”,使用“填补数据空白”和“填补空白Inventory Table' 用于计算运行/累积总数并加密数据。 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 并希望在 数据库中执行此操作。

谢谢!

【问题讨论】:

    标签: sql oracle elapsedtime


    【解决方案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;
    

    【讨论】:

      【解决方案2】:
      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 日开始的一周”)并以直接的方式处理年终展期。

      【讨论】:

      • 当您有几天的时间时,我会和您一起讨论日历算术 - 但是当您汇总数据(每周一个值)时会有所不同。当数据格式为 2011-43 (YYYY-WW) 时,您将如何计算?
      • 在我的回答中进一步讨论。
      猜你喜欢
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      相关资源
      最近更新 更多