简体   繁体   中英

DB2 - use field as a labeled duration for time calculation

Given a table that looks like this:

id  task                     scheduled_date    reminder
--  -----------------------  ----------------  --------
 1  mail january newsletter  2022-01-01        15 days

I had planned on executing a query to mimic date addition as in

SELECT TASK, SCHEDULED_DATE + 15 DAYS FROM ...

==> 2022-01-16

Unfortunately, using the REMINDER field gives an error:

SELECT TASK, (SCHEDULED_DATE + REMINDER) FROM ...

==>[Code: -182, SQL State: 42816]  [SQL0182] A date, time, or timestamp expression not valid.

Is there any way to accomplish using the reminder field as a labeled duration? (I'm using IBMi DB2)

You'll need to convert the string "15 days" into an actual duration.

A date durration is a decimal(8,0) number representing YYYYMMDD

So 15 days would be 00000015
1 year, 00010000
1 year 1 month, one day '00010101`

create table testdur (
  datedur decimal(8,0)
);

insert into testdur
  values (15), (10000), (10101), (90), (300);

select current_date as curDate
  , dateDur
  ,current_date + dateDur
from testdur;

Results
在此处输入图像描述

You may create a user defined finction for this.
I don't have Db2 for IBM i at hand, but it should work as for Db2 for LUW.

create or replace function add_interval
(
  p_date date
, p_interval varchar (100)
)
returns date
begin atomic
  declare v_pattern varchar (35) default '([+-]? *[0-9]+) *(day|month|year)';
  declare v_y int default 0;
  declare v_m int default 0;
  declare v_d int default 0;
  declare v_occ int default 1;
  declare v_num int;
  declare v_kind varchar (5);
  declare v_interval varchar (100);

  set v_interval = lower (p_interval);
  l1: while true do
    set v_kind = regexp_substr 
      (
        v_interval
      , v_pattern
      , 1, v_occ, '', 2
      );
    if v_kind is null then leave l1; end if;
    set v_num =
    int 
    (
      regexp_substr
      (
        v_interval
      , v_pattern
      , 1, v_occ, '', 1
      )
    );
    if v_kind = 'day' 
      then set v_d = v_d + v_num;
    elseif v_kind = 'month'
      then set v_m = v_m + v_num;
    elseif v_kind = 'year'
      then set v_y = v_y + v_num;
    end if;
    set v_occ = v_occ + 1;
  end while l1;
  return p_date 
    + v_y year
    + v_m month
    + v_d day
  ;
end
select 
  i
, add_interval (date ('2023-02-07'), i) d
from
(
  values
    ('15 days')
  , ('15day')
  , ('15days - 1 days + 1 month - 2 year')
) t (i)
I D
15 days 2023-02-22
15day 2023-02-22
15days - 1 days + 1 month - 2 year 2021-03-21

fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM