本篇是接續(xù)前一篇,因有朋友(allenc)要計(jì)算oracle的周數(shù)日期起迄,
所以測(cè)試了一下,
測(cè)試結(jié)果如下:
-- 特殊周數(shù)計(jì)算
-- 星期日到星期六為一周(與ww及iw算法不同)
-- 例2005年的第一周起迄是同一天,是20050101
-- 例2004年的第一周起為20040101迄為20040103
-- 計(jì)算第一周的天數(shù)
create or replace function fdf(p_date in date) return number
is
begin
-- 檢查是否傳入要計(jì)算那一年的一月一日
if to_char(to_char(p_date,‘ddd‘)) <> ‘001‘ then
return null;
end if;
--如果第一周的第一天剛好也是最后一天時(shí),傳回1
if to_char(p_date,‘d‘) <> ‘7‘ then
return (next_day(p_date,‘SATURDAY‘) - p_date +1);
else
return 1;
end if;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
計(jì)算公式:
起 :decode(周,1,計(jì)算當(dāng)年的一月一日,計(jì)算當(dāng)年的一月一日 + (fdf(計(jì)算當(dāng)年的一月一日) + (周 - 2)*7)) as 起
迄(第一種算法):decode(周,53,to_date(to_char(計(jì)算當(dāng)年的一月一日,‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),計(jì)算當(dāng)年的一月一日 + (fdf(計(jì)算當(dāng)年的一月一日) + (周-1)*7-1)) as 迄
迄(第二種算法):decode(周,53,last_day(trunc(計(jì)算當(dāng)年的一月一日,‘mm‘)+340),計(jì)算當(dāng)年的一月一日 + (fdf(計(jì)算當(dāng)年的一月一日) + (周-1)*7-1)) as 迄
上面的參數(shù)部份,"計(jì)算當(dāng)年的一月一日"為date type,"周"為number type
傳回值一律是date型態(tài)
例如:
--2004年第1周
select decode(1,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
--2004年第3周
select decode(3,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
--2004年第53周
select decode(53,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
--2005年第1周
select decode(1,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
--2005年第3周
select decode(3,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
--2005年第53周
select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
--2005年第53周方法2
select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,last_day(trunc(to_date(‘20050101‘,‘yyyymmdd‘),‘mm‘)+340),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
結(jié)果如下:
127.0.0.1:asdb:WF>--2004年第1周
127.0.0.1:asdb:WF>select decode(1,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
01-JAN-04 03-JAN-04
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2004年第3周
127.0.0.1:asdb:WF>select decode(3,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
11-JAN-04 17-JAN-04
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2004年第53周
127.0.0.1:asdb:WF>select decode(53,1,to_date(‘20040101‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20040101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20040101‘,‘yyyymmdd‘) + (fdf(to_date(‘20040101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
26-DEC-04 31-DEC-04
Elapsed: 00:00:00.01
127.0.0.1:asdb:WF>
127.0.0.1:asdb:WF>--2005年第1周
127.0.0.1:asdb:WF>select decode(1,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1 - 2)*7)) as s_week,decode(1,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (1-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
01-JAN-05 01-JAN-05
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2005年第3周
127.0.0.1:asdb:WF>select decode(3,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3 - 2)*7)) as s_week,decode(3,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (3-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
09-JAN-05 15-JAN-05
Elapsed: 00:00:00.00
127.0.0.1:asdb:WF>--2005年第53周
127.0.0.1:asdb:WF>select decode(53,1,to_date(‘20050101‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53 - 2)*7)) as s_week,decode(53,53,to_date(to_char(to_date(‘20050101‘,‘yyyymmdd‘),‘yyyy‘)||‘12‘||‘31‘,‘yyyymmdd‘),to_date(‘20050101‘,‘yyyymmdd‘) + (fdf(to_date(‘20050101‘,‘yyyymmdd‘)) + (53-1)*7-1)) as e_week from dual;
S_WEEK E_WEEK
--------- ---------
25-DEC-05 31-DEC-05
Elapsed: 00:00:00.01
127.0.0.1:asdb:WF>