473,383 Members | 1,742 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Calculating Business Days

Is anyone aware of a function (system or user defined) that will
calculate business days? For instance: I have a column in as table
called DATE. I want to be able to add five business days to that date
and come up with a new date. Is that possible.

Also, is there anyway that DB2 can be aware of holidays? Maybe load
them onto the server in some type of reference file or something.

I ask these questions because I'm working on a banking application and
these are two MAJOR hurdles for us to get over.

Any help would be appreciated.

Thanks!
Nov 12 '05 #1
12 23628
Sounds like a job for writing your own usder-defined functions.
This article might be a place to start:

http://www-106.ibm.com/developerwork.../0211yip3.html

Anthony Robinson wrote:
Is anyone aware of a function (system or user defined) that will
calculate business days? For instance: I have a column in as table
called DATE. I want to be able to add five business days to that date
and come up with a new date. Is that possible.

Also, is there anyway that DB2 can be aware of holidays? Maybe load
them onto the server in some type of reference file or something.

I ask these questions because I'm working on a banking application and
these are two MAJOR hurdles for us to get over.

Any help would be appreciated.

Thanks!


Nov 12 '05 #2
Ken
an*****@yahoo.com (Anthony Robinson) wrote in message news:<d1**************************@posting.google. com>...
<snip>
I ask these questions because I'm working on a banking application and
these are two MAJOR hurdles for us to get over.


You could create a time dimension table. These are commonly used in
star-schemas in data marts, but also provide some value in oltp
situations like you're describing. The time dimension would be faster
and easier to maintain than a procedure that needed to calculate
"first saturday of the month", etc.

A typical implementation would involve a primary key of date, with
non-key attributes describing the date. In a warehouse you'd be more
likely to use a surrogate key than date (or timestamp, etc), but
that's just an implementation detail. You could then also write stored
procedures that would access this table if you want to encapsulate it
behind an API.

ken
Nov 12 '05 #3
Ken:

Not to be a mooch, but could you give me an idea of how this would be
implemented? 've worked with date dimensions before, but am having a hard
time grasping the consept you're referring to.

Any further insight would be greatly appreciated.

thanks!

"Ken" <ke******@yahoo.com> wrote in message
news:ea**************************@posting.google.c om...
an*****@yahoo.com (Anthony Robinson) wrote in message news:<d1**************************@posting.google. com>... <snip>
I ask these questions because I'm working on a banking application and
these are two MAJOR hurdles for us to get over.


You could create a time dimension table. These are commonly used in
star-schemas in data marts, but also provide some value in oltp
situations like you're describing. The time dimension would be faster
and easier to maintain than a procedure that needed to calculate
"first saturday of the month", etc.

A typical implementation would involve a primary key of date, with
non-key attributes describing the date. In a warehouse you'd be more
likely to use a surrogate key than date (or timestamp, etc), but
that's just an implementation detail. You could then also write stored
procedures that would access this table if you want to encapsulate it
behind an API.

ken

Nov 12 '05 #4
AK
Here is Oracle PL/SQl script that accomplishes just that
It's just as easy in DB2
replace ROWNUM with ROW_NUMBER() and some oither functions such as TRUNC

DROP TABLE SD_CALENDAR;
CREATE TABLE SD_CALENDAR(
BUSINESS_NUM NUMBER(5) NOT NULL,
NUM NUMBER(5) NOT NULL,
SD_DAY DATE NOT NULL,
DAY_OF_WEEK NUMBER(1) NOT NULL,--0 - Sun,..., 6 - Sat
DAY_TYPE NUMBER(2) NOT NULL,
SD_YEAR NUMBER(4) NOT NULL,
SD_MONTH NUMBER(2) NOT NULL
);

INSERT INTO SD_CALENDAR(BUSINESS_NUM, NUM, SD_DAY, DAY_OF_WEEK, DAY_TYPE,
SD_YEAR, SD_MONTH)
SELECT 0 AS BUSINESS_NUM,
N AS NUM,
(TO_DATE('09/01/2003', 'MM/DD/YYYY') + N) AS SD_DAY,
MOD(N+1, 7) AS DAY_OF_WEEK,
CASE MOD(N+1, 7)
WHEN 0 THEN 1
WHEN 6 THEN 1
ELSE 0
END AS DAY_TYPE,
0 AS SD_YEAR,
0 AS SD_MONTH
FROM
(select (rownum-1) AS N from user_tAB_COLUMNS WHERE ROWNUM<1000) SEQ;
COMMIT;

--- UPDATE HERE HOLIDAY SCHEDULE FOR 2003 / 2004 ---------------

UPDATE SD_CALENDAR
SET BUSINESS_NUM = (SELECT COUNT(*) FROM SD_CALENDAR S1 WHERE S1.NUM <
SD_CALENDAR.NUM AND S1.DAY_TYPE=0),
SD_YEAR = EXTRACT(YEAR FROM SD_DAY),
SD_MONTH = EXTRACT(MONTH FROM SD_DAY);
COMMIT;

CREATE INDEX CALENDAR_DAY ON SD_CALENDAR(SD_DAY);
CREATE INDEX CALENDAR_NUM ON SD_CALENDAR(BUSINESS_NUM);
CREATE INDEX CALENDAR_YEAR ON SD_CALENDAR(SD_YEAR, SD_MONTH);


CREATE OR REPLACE FUNCTION ADD_BUSINESS_DAYS(DATE_FROM IN DATE, DAYS_ADD IN
NUMBER)
RETURN DATE
IS RET DATE;
BEGIN
SELECT SD_TO.SD_DAY
INTO RET
FROM
SD_CALENDAR SD_FROM,
SD_CALENDAR SD_TO
WHERE SD_FROM.SD_DAY = TRUNC(DATE_FROM, 'DDD')
AND SD_FROM.BUSINESS_NUM + DAYS_ADD = SD_TO.BUSINESS_NUM
AND SD_TO.DAY_TYPE = 0;
RETURN(RET);
END;
/
Nov 12 '05 #5
Ken
"Anthony Robinson" <mr********@mn.rr.com> wrote in message news:<xn*******************@twister.rdc-kc.rr.com>...
Not to be a mooch, but could you give me an idea of how this would be
implemented?


No problem at all. AK has probably already answered this for you, but
in case you aren't familiar with PL/SQL...here's a little more info.
A typical time dimension table will look something like this:

CREATE TABLE md_time_to_day (
time_id INTEGER NOT NULL, # 1 = 2004/01/01
through 1460 = 2008/01/01
date DATE NOT NULL,
year INTEGER NOT NULL, # 2004, etc
month_of_year INTEGER NOT NULL, # 1-12
day_of_month INTEGER NOT NULL, # 1-31
quarter INTEGER NOT NULL, # 1-4
week_of_year INTEGER NOT NULL, # 1-52
day_of_week VARCHAR(10) NOT NULL, # 'monday', etc
season VARCHAR(10) NOT NULL, # 'summer', etc
part_of_week CHAR(03) NOT NULL, # 'day' or 'end'
federal_holiday CHAR(03) NOT NULL, # 'yes' or 'no'
state_holiday CHAR(03) NOT NULL, # 'yes' or 'no'
company_holiday CHAR(03) NOT NULL # 'yes' or 'no'
) IN ts_dim
;
ALTER TABLE md_time_to_day ADD CONSTRAINT md_time_to_day_pk PRIMARY
KEY (time_id);
ALTER TABLE md_time_to_day ADD CONSTRAINT md_time_to_day_x2 UNIQUE
(date);

Now, you can populate a table like this from a pl/sql script like AK
provided, a script (python, perl, etc), etc.

Ken
Nov 12 '05 #6
ak************@yahoo.com (AK) wrote in message news:<46**************************@posting.google. com>...
Here is Oracle PL/SQl script that accomplishes just that
It's just as easy in DB2
replace ROWNUM with ROW_NUMBER() and some oither functions such as TRUNC

DROP TABLE SD_CALENDAR;
CREATE TABLE SD_CALENDAR(
BUSINESS_NUM NUMBER(5) NOT NULL,
NUM NUMBER(5) NOT NULL,
SD_DAY DATE NOT NULL,
DAY_OF_WEEK NUMBER(1) NOT NULL,--0 - Sun,..., 6 - Sat
DAY_TYPE NUMBER(2) NOT NULL,
SD_YEAR NUMBER(4) NOT NULL,
SD_MONTH NUMBER(2) NOT NULL
);

INSERT INTO SD_CALENDAR(BUSINESS_NUM, NUM, SD_DAY, DAY_OF_WEEK, DAY_TYPE,
SD_YEAR, SD_MONTH)
SELECT 0 AS BUSINESS_NUM,
N AS NUM,
(TO_DATE('09/01/2003', 'MM/DD/YYYY') + N) AS SD_DAY,
MOD(N+1, 7) AS DAY_OF_WEEK,
CASE MOD(N+1, 7)
WHEN 0 THEN 1
WHEN 6 THEN 1
ELSE 0
END AS DAY_TYPE,
0 AS SD_YEAR,
0 AS SD_MONTH
FROM
(select (rownum-1) AS N from user_tAB_COLUMNS WHERE ROWNUM<1000) SEQ;
COMMIT;

--- UPDATE HERE HOLIDAY SCHEDULE FOR 2003 / 2004 ---------------

UPDATE SD_CALENDAR
SET BUSINESS_NUM = (SELECT COUNT(*) FROM SD_CALENDAR S1 WHERE S1.NUM <
SD_CALENDAR.NUM AND S1.DAY_TYPE=0),
SD_YEAR = EXTRACT(YEAR FROM SD_DAY),
SD_MONTH = EXTRACT(MONTH FROM SD_DAY);
COMMIT;

CREATE INDEX CALENDAR_DAY ON SD_CALENDAR(SD_DAY);
CREATE INDEX CALENDAR_NUM ON SD_CALENDAR(BUSINESS_NUM);
CREATE INDEX CALENDAR_YEAR ON SD_CALENDAR(SD_YEAR, SD_MONTH);


CREATE OR REPLACE FUNCTION ADD_BUSINESS_DAYS(DATE_FROM IN DATE, DAYS_ADD IN
NUMBER)
RETURN DATE
IS RET DATE;
BEGIN
SELECT SD_TO.SD_DAY
INTO RET
FROM
SD_CALENDAR SD_FROM,
SD_CALENDAR SD_TO
WHERE SD_FROM.SD_DAY = TRUNC(DATE_FROM, 'DDD')
AND SD_FROM.BUSINESS_NUM + DAYS_ADD = SD_TO.BUSINESS_NUM
AND SD_TO.DAY_TYPE = 0;
RETURN(RET);
END;
/


Thanks - I'll set to work on decoding this for DB2. One question: what
is the DB2 equivalent of TO_DATE (or what does TO_DATE do in Oracle),
and why do you set it to 09/01/2003?

How does this scenario perform in a production environment? Are there
some drawbacks with having to use a table to do the calculations? How
is concurrency? We'll be having anywhere from 100 to 10,000 users at
some point and want to mke sure that whatever solution I implement
will be able to handle the load.

Thanks for all the help...
Nov 12 '05 #7
Hi Anthony,
Is anyone aware of a function (system or user defined) that will
calculate business days? For instance: I have a column in as table
called DATE. I want to be able to add five business days to that date
and come up with a new date. Is that possible.


As has been posted, you need to roll your own. It's easy enough to
maintain your own holidays table. From this you can generate your own
business days table and then calculate the next business day any
number of days into the future. Below is how I'd do it...

-- Table to store public holidays. Store as much info on the holidays
-- as you like. I've always only needed the description.
CREATE TABLE HOLIDAYS (
HOLIDAY_DATE DATE NOT NULL
, H0LIDAY_DESC VARCHAR(25) NOT NULL WITH DEFAULT
, CONSTRAINT PK_HOL PRIMARY KEY (HOLIDAY_DATE)
);

-- insert some holidays
INSERT INTO HOLIDAYS (
HOLIDAY_DATE
, H0LIDAY_DESC
)
VALUES ('2004-01-01', 'New Years Day')
,('2004-01-26', 'Australia Day')
,('2004-12-25', 'Christmas Day')
,('2004-12-26', 'Boxing Day')
,('2004-12-27', 'Christmas Day Holiday')
,('2004-12-28', 'Boxing Day Holiday');
-- Create a table function to return the business days in a year
-- excluding weekends. You can make the range anything relative
-- to the supplied date. I've gone with a year in advance.
CREATE FUNCTION BUSINESS_DATES (START_DATE DATE)
RETURNS TABLE ( BUS_DAY_SEQ INTEGER
, CAL_DATE DATE
, DAY_NAME VARCHAR(15))
LANGUAGE SQL
READS SQL DATA
NO EXTERNAL ACTION
DETERMINISTIC
RETURN
with calender(BASE_DATE, CAL_DATE)
as(
VALUES (START_DATE, START_DATE)
union all
select BASE_DATE
, cal_date + 1 day
from calender
where cal_date + 1 DAYS < BASE_DATE + 1 YEAR
)
select ROW_NUMBER() OVER() AS BUS_DAY_SEQ
, CAL_DATE
, DAYNAME(CAL_DATE)
from calender c
where DAYOFWEEK(cal_date) not in (1,7)
AND NOT EXISTS (SELECT *
FROM HOLIDAYS H
WHERE H.HOLIDAY_DATE = C.CAL_DATE);

-- Test the table function.
SELECT *
FROM TABLE (BUSINESS_DATES (CURRENT DATE) ) T;

-- Create a scalar function to get the next business day
-- n days from the supplied date.
CREATE FUNCTION NEXT_BUS_DATE (CURR_BUS_DATE DATE
, DAYS_FROM_DATE INTEGER)
RETURNS DATE
LANGUAGE SQL
READS SQL DATA
NO EXTERNAL ACTION
DETERMINISTIC
RETURN
SELECT C3.CAL_DATE
FROM (
SELECT C.BUS_DAY_SEQ
,C.CAL_DATE
FROM TABLE (BUSINESS_DATES (CURR_BUS_DATE) ) C
,(SELECT MIN(CAL_DATE) AS CAL_DATE
FROM TABLE (BUSINESS_DATES (CURR_BUS_DATE) ) T
WHERE CAL_DATE >= CURR_BUS_DATE
) T1
WHERE C.CAL_DATE = T1.CAL_DATE
) C2
, TABLE (BUSINESS_DATES (CURR_BUS_DATE) ) C3
WHERE C2.BUS_DAY_SEQ + DAYS_FROM_DATE = C3.BUS_DAY_SEQ;
-- Test the use of the scalar function
values (NEXT_BUS_DATE (DATE('2004-01-23'), 5));

Christian.
Nov 12 '05 #8
AK
> >
INSERT INTO SD_CALENDAR(BUSINESS_NUM, NUM, SD_DAY, DAY_OF_WEEK, DAY_TYPE,
this statement populates the calendar table with thousands of rows. We
ran in just once.
SD_YEAR, SD_MONTH)
SELECT 0 AS BUSINESS_NUM,
N AS NUM,
(TO_DATE('09/01/2003', 'MM/DD/YYYY') + N) AS SD_DAY,
Now the table contains several thousand consecutive dates starting
from September 2003.
I needed dates starting from '09/01/2003'. In DB2 use DATE function.
Refer to Paul Yip's article on DB2DD (Fun with Dates)

CREATE OR REPLACE FUNCTION ADD_BUSINESS_DAYS(DATE_FROM IN DATE, DAYS_ADD IN
this function performs very fast, it is a self join on an indexed
column
NUMBER)
RETURN DATE
IS RET DATE;
BEGIN
SELECT SD_TO.SD_DAY
INTO RET
FROM
SD_CALENDAR SD_FROM,
SD_CALENDAR SD_TO
WHERE SD_FROM.SD_DAY = TRUNC(DATE_FROM, 'DDD')
AND SD_FROM.BUSINESS_NUM + DAYS_ADD = SD_TO.BUSINESS_NUM
AND SD_TO.DAY_TYPE = 0;
RETURN(RET);
END;
/


How does this scenario perform in a production environment? Are there
some drawbacks with having to use a table to do the calculations? How
is concurrency? We'll be having anywhere from 100 to 10,000 users at
some point and want to mke sure that whatever solution I implement
will be able to handle the load.


I've successfully used calendar tables in DB2. Performance is usually
very good, because queries with calendar tables are usually simpler,
and simpler queries have better chances to get good execution plans

I've posted an Oracle script, because it accomplishes exactly what you
need.
It's used in a production database with 25+ terabytes of data and
1,500+ users
Performs very well.
Nov 12 '05 #9
ch**************@techie.com (Christian Maslen) wrote in message news:<b9**************************@posting.google. com>...
Hi Anthony,
Is anyone aware of a function (system or user defined) that will
calculate business days? For instance: I have a column in as table
called DATE. I want to be able to add five business days to that date
and come up with a new date. Is that possible.


Hi!

Although it is not an exact answer to your question, but if you are
interested, I have a tool which does much dirty work for you and
creates a very powerfull time dimension structure for you (more than
200 attributes are currently available). It supports generating
various calendar related attributes like the number of days to the
next holiday, the number of holiday days in a period and so on.
If you are interested I can send you a more complete description.
Write me at li********@mail.ru

Best regards,
Konstantin
Nov 12 '05 #10
AK
Christian,

I think your approach runs slower than mine if you need to add, for
instance, 10 business days. Also your approach would work 10 times
slower when adding 100 business days, because it menas 10 times more
iterations.
Also I think your approach uses up significantly more CPU, which is
precious because processors are pricey and IBM charges by the
processor too.

What do you think?
Nov 12 '05 #11
Hi AK,
I think your approach runs slower than mine if you need to add, for
instance, 10 business days. Also your approach would work 10 times
slower when adding 100 business days, because it menas 10 times more
iterations.


I used a generalised calender function (always returns a year of
days), you can add a day count parameter to the calendar function so
it wouldn't waste iterations.

I'd say there is a good chance a permanent calendar table and a
function built on top would run faster than a generated calendar, but
you never know - unless you have the time to test it out (Serge would
have a better idea of the performance than me). I just thought it was
worth presenting an alternative approach.

Christian.
Nov 12 '05 #12
AK
Hi Christian,

I'd say there is a good chance a permanent calendar table and a
function built on top would run faster than a generated calendar, but
you never know - unless you have the time to test it out (Serge would
have a better idea of the performance than me). I just thought it was
worth presenting an alternative approach.


I was doing comparisons like that 2 years ago with 7.1, at that time
recursion was consistently MUCH slower and it was using more CPU.
Since then, a lot could have changed, but I haven't re-evaluated that
old decision to avoid recursion whenever possible

One more thing: a query with a simple SQL UDF like the one I posted
might be re-written by the optimizer and get a much better plan. I
think queries with recursion cannot be rewritten.

Please correct me if I'm wrong
Nov 12 '05 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: David Stockwell | last post by:
I''m wondering if the Calendar object has an option to only do calculations based on business days (ie M-F). Additionally does it have a way to get holidays into itself? Currently I'm...
1
by: igendreau | last post by:
I have users inputting a "Request Date". Upon entering a date, I need Access to populate a second field ("Due Date"). When they enter their Request Date, I want Access to set the default value of...
7
by: Sam | last post by:
Hi, I use C# in my ASP.NET projects. Here's what I need to do: I want to add x business days to a given date i.e. add 12 business days to today's date. What is the best, fastest and most...
8
by: =?Utf-8?B?QWw=?= | last post by:
I am working in vb2005. how can I calculate business days (not including holidays and weekends) between 2 dates? thanks Al
1
by: santhoshrms | last post by:
I need to be able to determine the number of business days between two dates. Is there a function/Select Query in DB2 that can be used to do this? ...
1
by: ArchMichael | last post by:
i need help again on calculating business days excluding holidays i have a field called assign date and i need to calculate 7 business days excluding holidays ( already have a table for holiday)...
5
FishVal
by: FishVal | last post by:
IMHO, the following is not a how-to-do instruction to solve a particular problem but more a concept-proof stuff demonstrating possibilities of SQL. So, let us say the problem is to calculate...
0
by: josephsimonbenn | last post by:
I need to calculate the number of business days employees work in each month using vba. The problem is, some employees work 3 days, some 4 and some 5. So i want to be able to turn on/off the days...
3
by: PotatoChip | last post by:
I'm working in an Access XP database and I need to create a query which calculates what the date will be 6 business days after . I have no idea where to start and most posts I find on calculating...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.