从ISO日期开始的Oracle周数,但从12月1日起

时间:2016-11-02 18:13:01

标签: oracle date

好的,我的查询工作正常,从12月1日(我们的销售财年开始)计算周数。

现在要求已经改变了。我仍然需要根据字段(Invoice_Date)计算周数。但是,现在我需要从最近的星期一到12月1日开始计算,而不是从12月1日(12月1日到7日,第1周等)开始计算。据我了解,ISO周是我正在寻找的,但从1月1日开始。如何从12月1日开始修改它?

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

select next_day(to_date('0112' || to_char(sysdate, 'YYYY'),'ddmmyyyy') - 1, 'MONDAY') dec_mon from dual;
给你当年12月的第一个星期一

周数仅为ceil((sysdate - dec_mon)/7)

如果您希望在12月1日之前的上周一,可以通过以下方式获取:

select next_day(to_date('2511' || to_char(sysdate, 'YYYY'),'ddmmyyyy') - 1, 'MONDAY') 
from dual;

答案 1 :(得分:0)

在这个提议的解决方案中,我首先构建一个“帮助表”,显示每个会计年度的Monday_fromMonday_to(在第三个CTE中,名为ranges)。然后我构建了一些测试日期 - 我很懒,我应该使用to_date()所以我也可以包含时间组件。实际解决方案中的连接条件(在代码末尾)被写入,因此无需修改具有非零“时间”组件的日期即可工作。

我使用了Oracle 11.2的优点,它允许我们在CTE声明中给出列别名 - 否则列别名需要在相应的SELECT内移动。否则,解决方案至少应该适用于Oracle 9及更高版本(我认为)。

with
     y ( dt ) as (
       select add_months(date '2000-12-01', 12 * level )
       from   dual
       connect by level <= 30
     ),
     m ( dt ) as (
       select trunc(dt, 'iw') + case when dt - trunc(dt, 'iw') <= 3 then 0 else 7 end
       from   y       
     ),
     ranges ( monday_from, monday_to ) as (
       select dt, lead(dt) over (order by dt) - 1
       from   m
     ),
     test_dates ( t_date ) as (
       select date '2013-02-23' from dual union all
       select date '2008-12-01' from dual union all
       select date '2008-04-28' from dual union all
       select date '2016-11-29' from dual
     )
select t_date, monday_from, 1 + trunc((t_date - monday_from)/7) as week_no
from   test_dates t inner join ranges r
       on t.t_date >= r.monday_from and t.t_date < r.monday_to
;

T_DATE              MONDAY_FROM            WEEK_NO
------------------- ------------------- ----------
2008-04-28 00:00:00 2007-12-03 00:00:00         22
2008-12-01 00:00:00 2008-12-01 00:00:00          1
2013-02-23 00:00:00 2012-12-03 00:00:00         12
2016-11-29 00:00:00 2016-11-28 00:00:00          1

答案 2 :(得分:0)

使用以下函数返回距离任何给定日期最近的星期一:

NEXT_DAY(some_date-4,'Monday')

如此查询所示:

with dts(some_date) as (
  select date '2006-12-1' from dual
  union all
  select add_months(some_date,12)
    from dts
   where some_date <= date '2014-12-1'
)
select some_date
     , next_day(some_date-4,'monday') nearest
     , some_date - next_day(some_date-4,'monday') dist
  from dts;

SOME_DATE   NEAREST           DIST
----------- ----------- ----------
01-DEC-2006 04-DEC-2006         -3
01-DEC-2007 03-DEC-2007         -2
01-DEC-2008 01-DEC-2008          0
01-DEC-2009 30-NOV-2009          1
01-DEC-2010 29-NOV-2010          2
01-DEC-2011 28-NOV-2011          3
01-DEC-2012 03-DEC-2012         -2
01-DEC-2013 02-DEC-2013         -1
01-DEC-2014 01-DEC-2014          0
01-DEC-2015 30-NOV-2015          1

 10 rows selected