我有一个周期存储在数据库中,周期是在VARCHAR2()
示例:2014019 它表示2014年的第19周
我想在周期间做加/减操作,2014019 + 1将是2014020
但我不能正常加/减,因为2014052(2014年的最后一周)+ 1 = 2014053这是错误的。
2014052 + 1 = 2015001这是正确的。
知道如何使用sql / store过程解决这个问题?
答案 0 :(得分:0)
如果你总是有相同的长度字符串(4位+'0'+ 2位),你可以简单地将其子串: (增加闰年逻辑)
DECLARE lvchInput VARCHAR2(7);
lvchOutput VARCHAR2(7);
lnYear NUMBER;
lnWeek NUMBER;
lbLeap BOOLEAN;
BEGIN
lvchInput := '2012052';
lnYear := to_number(SubStr(lvchInput, 1, 4));
lnWeek := to_number(SubStr(lvchInput, 6, 2));
IF (Mod(lnYear, 4) = 0 AND Mod(lnYear, 100) <> 0) OR Mod(lnYear, 400) = 0 THEN
lbLeap := TRUE;
ELSE
lbLeap := FALSE;
END IF;
DBMS_OUTPUT.PUT_LINE('lbLeap = ' || CASE WHEN lbLeap = TRUE THEN 'True' ELSE 'False' END);
DBMS_OUTPUT.PUT_LINE('lnYear = ' || to_char(lnYear));
DBMS_OUTPUT.PUT_LINE('lnWeek = ' || to_char(lnWeek));
IF (lbLeap AND lnWeek >= 53) OR
(NOT lbLeap AND lnWeek >= 52) THEN
lnWeek := 0;
lnYear := lnYear + 1;
END IF;
lnWeek := lnWeek + 1;
lvchOutput := to_char(lnYear) || '0' || LPad(to_char(lnWeek), 2, '0');
DBMS_OUTPUT.PUT_LINE('lvchOutput = ' || lvchOutput);
END;
答案 1 :(得分:0)
编辑:增加OP要求的闰年条件。
编辑2:忘记检查YEAR之后的新年份:=年+ 1是闰年。添加了条件和测试用例。
CREATE OR REPLACE FUNCTION ADD_WEEK (p_date IN VARCHAR2, nrOfWeeks IN NUMBER)
RETURN VARCHAR2
AS
RESULT VARCHAR2 (8);
YEAR NUMBER;
WEEK NUMBER;
LEAP_LIMIT NUMBER;
BEGIN
YEAR := SUBSTR (p_date, 1, 4);
WEEK := SUBSTR (p_date, 6, 2);
IF (MOD (YEAR, 400) = 0)
THEN
LEAP_LIMIT := 54;
ELSIF (MOD (YEAR, 100) = 0)
THEN
LEAP_LIMIT := 53;
ELSIF (MOD (YEAR, 4) = 0)
THEN
LEAP_LIMIT := 54;
ELSE
LEAP_LIMIT := 53;
END IF;
FOR i IN 1 .. nrOfWeeks
LOOP
WEEK := WEEK + 1;
IF WEEK >= LEAP_LIMIT
THEN
WEEK := 1;
YEAR := YEAR + 1;
END IF;
--check if the resulted year is a leap year before reentering the loop
IF (MOD (YEAR, 400) = 0)
THEN
LEAP_LIMIT := 54;
ELSIF (MOD (YEAR, 100) = 0)
THEN
LEAP_LIMIT := 53;
ELSIF (MOD (YEAR, 4) = 0)
THEN
LEAP_LIMIT := 54;
ELSE
LEAP_LIMIT := 53;
END IF;
END LOOP;
RESULT :=
YEAR
|| '0'
|| (CASE
WHEN week < 10 THEN '0' || TO_CHAR (week)
ELSE TO_CHAR (week)
END);
RETURN RESULT;
END ADD_WEEK;
例如可以调用(根据需要添加多周)
select ADD_WEEK('2014052',2) AS RESULT from dual
产生
的结果2015002
闰年
select ADD_WEEK('2012052',1) AS RESULT from dual
输出:
2012053
增加许多周并跟踪闰年
2012 -53
2013 -52
2014 -52
2015 -52
total of 53+3*52=209 weeks, should give result of 2016001 if starting from 2012001
select ADD_WEEK('2012001',209) AS RESULT from dual
结果是:
2016001
答案 2 :(得分:0)
create or replace function add_weeks(f_week_period in varchar2, f_weeks_to_add NUMBER, f_fmt varchar2) return varchar2 as
l_year integer;
l_weeks integer;
l_last integer;
begin
l_year := to_number(substr(f_week_period, 1, 4));
l_weeks := to_number(substr(f_week_period, -2, 2)) + f_weeks_to_add;
while true loop
-- get the max number of weeks in the year
l_last := to_number(to_char(to_date(l_year || '1231', 'YYYYMMDD'), f_fmt));
-- IW can return 1
if l_last = 1 then
l_last := to_number(to_char(to_date(l_year || '1224', 'YYYYMMDD'), f_fmt));
end if;
if (l_last >= l_weeks) then
exit;
else
l_weeks := l_weeks - l_last;
l_year := l_year + 1;
end if;
end loop;
return l_year || '0' || l_weeks;
end add_weeks;
用法:
-- ISO weeks
select add_weeks('2014019', 50, 'IW') from dual;
-- WW weeks
select add_weeks('2014019', 50, 'WW') from dual;
功能仅适用于正f_weeks_to_add
(但修改它以使用负数并不困难)。
f_fmt
可以使用&#39; WW&#39;或者&#39; IW&#39;