DB2 - Determine a future date based on two fields - db2

I need to calculate a date in DB2 for UNIX.
I have a date field:
CONTRACT_DT (Examples:
2/7/2006,
8/25/2006,
11/16/2007,
2/25/2008,
12/29/2005)
And a type field
PRIME (Examples: C, I, E, Z, V, K)
I need to calculate the next date the loan will be reviewed (REVIEW_DT).
If Prime = Z then every year from CONTRACT_DT
If Prime = V then every three years from CONTRACT_DT
If Prime = K then every five years from CONTRACT_DT
If Prime = NULL or any other letter, then NULL
An example is loan 01 has a CONTRACT_DT of 3/1/2004, and has a PRIME of V.
So I need to count by/add three years to 3/1/2004, until I get a date greater than MTHLY_CLOSE_DT. (Options would be 2007, 2010, 2013, 2016, 2019,2022).
So correct answer is 3/1/2016.
I realize the structure is a CASE statement, but I have no idea how to pick a date based on year multiples and find the one greater than MNTHLY_CLOSE_DT.
Here's what I have so far:
CREATE PROCEDURE "FINANCE"."AL_LOOP_TEST"(OUT r_rvdt DATE)
BEGIN ATOMIC
DECLARE v_tmgi DATE;
DECLARE v_ctdt DATE;
DECLARE v_rvdt DATE;
SET v_tmgi = '2014-09-01'; --Close month
SET v_ctdt = '2012-06-02'; -- CONTRACT_DT
SET v_rvdt = v_ctdt; -- Starting Value for v_rvdt
WHILE (v_rvdt < v_tmgi) -- While Review Dt is less than Close Month
DO
SET v_rvdt = (v_rvdt + 5 YEAR); -- Add 5 years to date
END WHILE;
SET r_rvdt = v_rvdt;
END
Thanks!

Jimmy, Thanks for your help. This is what I created:
CREATE PROCEDURE "X"."AL_LOOP_TEST" ( OUT "R_RVDT" DATE )
LANGUAGE SQL
NOT DETERMINISTIC
EXTERNAL ACTION
MODIFIES SQL DATA
OLD SAVEPOINT LEVEL
BEGIN ATOMIC
DECLARE v_tmgi DATE;
DECLARE v_ctdt DATE;
DECLARE v_rvdt DATE;
SET v_tmgi = '2014-09-01'; --Close month
SET v_ctdt = '2002-06-02'; -- CONTRACT_DT
SET v_rvdt = v_ctdt; -- Starting Value for v_rvdt
WHILE (v_rvdt < v_tmgi) -- While Review Dt is less than Close Month
DO
SET v_rvdt = (v_rvdt + 5 YEAR); -- Add 5 years to date
END WHILE;
SET r_rvdt = v_rvdt;
END;

Related

How to find out Number of Workdays between two dates in HANA?

How to find out Number of Workdays(Monday to Friday) between two dates in SAP HANA ? We do not have to consider holidays.
We cant use WORKDAYS_BETWEEN() as we do not have TFACS table.
Here is how you can so ist in sql:
Calculate the number of whole weeks, multiply by 5
Add the remaining days: subtract weekday start date from weekday end date, correct for weekends (least...), Correct for carry-over (+5)
The second part can be simplified a little so that you don't have to write the subtraction twice.
Here an example with start date '2015-12-04' and end date '2015-12-19):
SELECT ROUND( DAYS_BETWEEN (TO_DATE ('2015-12-04', 'YYYY-MM-DD'), TO_DATE('2015-12-19', 'YYYY-MM-DD')) / 7, 0, ROUND_DOWN) * 5
+ ( case
when WEEKDAY (TO_DATE('2015-12-19', 'YYYY-MM-DD') ) - WEEKDAY (TO_DATE('2015-12-04', 'YYYY-MM-DD')) >= 0
then least( WEEKDAY (TO_DATE('2015-12-19', 'YYYY-MM-DD')), 5) - least( WEEKDAY (TO_DATE('2015-12-04', 'YYYY-MM-DD')), 5)
else
least( WEEKDAY (TO_DATE('2015-12-19', 'YYYY-MM-DD')), 5) - least( WEEKDAY (TO_DATE('2015-12-04', 'YYYY-MM-DD')), 5) + 5
end )
"Workdays" FROM DUMMY;
--> 11
I preferred to create a user defined function here to use in HANA SQLScript codes as follows
Create Function CalculateWorkDays (startdate date, enddate date)
returns cnt integer
LANGUAGE SQLSCRIPT AS
begin
declare i int;
cnt := 0;
i := 0;
while :i <= days_between(:startdate, :enddate)
do
if WEEKDAY( ADD_DAYS(:startdate,:i) ) < 5
then
cnt := :cnt + 1;
end if;
i := :i + 1;
end while;
end;
Please note that the above code block seems to contain an unnecessary loop.
On the other hand, if you have additional tables like department holidays, or personal holidays, etc. It might be useful to check these tables in the WHILE loop. Please refer to following SQL tutorial Calculate the Count of Working Days Between Two Dates where I created a similar SQL function checking custom work calendars or holiday calendars.
Here is how you call the function as sample
select CalculateWorkDays('20170101', '20170131') as i from dummy;
I hope it helps,

removing day portion of date variable for time series SAS

I'm having some frustration with dates in SAS.
I am using proc forecast and am trying make my dates spread evenly. I did some pre-processing wiht proc sql to get my counts by month but my dates are incorrect.
Though my dataset looks good (b/c I used format MONYY.) the actual value of that variable is wrong.
date year month count
Jan10 2010 1 100
Feb10 2010 2 494
...
..
.
The Date value is actually the full SAS representation of the date (18267), meaning that it includes the day count.
Do I need to convert the variable to a string and back to a date or is there a quick proc i can run?
My goal is to use the date variable with proc forecast so I only want Month and year.
Thanks for any help!
You can't define a date variable in SAS (so the number of days passed from 1jan1960) excluding the day.
What you can do is to hide the day with a format like monyy. but the underlying number will always contain that information.
Maybe you can use the interval=month option in proc forecast?
Please add some detail about the problem you're encountering with the forecast procedure.
EDIT: check this example:
data past;
keep date sales;
format date monyy5.;
lu = 0;
n = 25;
do i = -10 to n;
u = .7 * lu + .2 * rannor(1234);
lu = u;
sales = 10 + .10 * i + u;
date = intnx( 'month', '1jul1991'd, i - n );
if i > 0 then output;
end;
run;
proc forecast data=past interval=month lead=10 out=pred;
var sales;
id date;
run;

Postgresql function for checking date ranges

I'm not sure how to check for date ranges using a postgres function. What I want to do is check if a date falls within a certain range (with leeway of a week before the starting date)
So basically, I want to check if a date is between 7 days before to current date, and if so I'll return the id of that row.
create or replace function eight(_day date) returns text as $$
declare
r record;
check alias for $1;
startDate date;
begin
for r in
select * from terms
order by starting;
loop
startDate := r.starting;
if check between (..need help to create 7 days before startDate) and startDate return r.id;
end;
$$ language plpgsql;
I also have to check if the previous record's ending date collides with the startDate - 7days. How would I check the previous record?
Sounds like you want to use an interval:
startDate - interval '...'
I won't say any more than this since you're doing homework.
Dates work with integer math.
startdate - 8 is equivalent to (startdate::timestamp - '8 days'::interval)::date

T-sql IF Condition date evaluation

I have a simple question regarding T-SQL. I have a stored procedure which calls a Function which returns a date. I want to use an IF condition to compare todays date with the Functions returned date. IF true to return data.
Any ideas on the best way to handle this. I am learning t-sql at the moment and I am more familar with logical conditions from using C#.
ALTER FUNCTION [dbo].[monday_new_period](#p_date as datetime) -- Parameter to find current date
RETURNS datetime
BEGIN
-- 1 find the year and period given the current date
-- create parameters to store period and year of given date
declare #p_date_period int, #p_date_period_year int
-- assign the values to the period and year parameters
select
#p_date_period=period,
#p_date_period_year = [year]
from client_week_uk where #p_date between start_dt and end_dt
-- 2 determine the first monday given the period and year, by adding days to the first day of the period
-- this only works on the assumption a period lasts a least one week
-- create parameter to store the first day of the period
declare #p_start_date_for_period_x datetime
select #p_start_date_for_period_x = min(start_dt)
from client_week_uk where period = #p_date_period and [year] = #p_date_period_year
-- create parameter to store result
declare #p_result datetime
-- add x days to the first day to get a monday
select #p_result = dateadd(d,
case datename(dw, #p_start_date_for_period_x)
when 'Monday' then 0
when 'Tuesday' then 6
when 'Wednesday' then 5
when 'Thursday' then 4
when 'Friday' then 3
when 'Saturday' then 2
when 'Sunday' then 1 end,
#p_start_date_for_period_x)
Return #p_result
END
ALTER PROCEDURE [dbo].[usp_data_to_retrieve]
-- Add the parameters for the stored procedure here
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF monday_new_period(dbo.trimdate(getutcdate()) = getutcdate()
BEGIN
-- SQL GOES HERE --
END
Thanks!!
I assume you are working on Sql2008. See documentation of IF and CASE keywords for more details.
CREATE FUNCTION dbo.GetSomeDate()
RETURNS datetime
AS
BEGIN
RETURN '2012-03-05 13:12:14'
END
GO
IF CAST(GETDATE() AS DATE) = CAST(dbo.GetSomeDate() AS DATE)
BEGIN
PRINT 'The same date'
END
ELSE
BEGIN
PRINT 'Different dates'
END
-- in the select query
SELECT CASE WHEN CAST(GETDATE() AS DATE) = CAST(dbo.GetSomeDate() AS DATE) THEN 1 ELSE 0 END AS IsTheSame
This is the basic syntax for a T-SQL IF and a date compare.
If you are comparing just the date portion for equality you will need to use:
select dateadd(dd,0, datediff(dd,0, getDate()))
This snippet will effectively set the time portion to 00:00:00 so you can compare just dates. So in use it will look something like this.
IF dateadd(dd,0, datediff(dd,0, fn_yourFunction())) = dateadd(dd,0, datediff(dd,0, GETDATE()))
BEGIN
RETURN SELECT * FROM SOMEDATA
END
Hope that helps!

Count differnce of two Date's with Respect that every month has EXACT 30 days

I thought it was clear, but doesn't seem so.
This question is about T-SQL (since it's tagged with tsql :) )
So I couldn't find any out-of-the-box solution to calculate my problem.
Let's assume you have these two dateTimes:
DECLARE #start DATETIME = '2011-01-01',
#end DATETIME = '2011-04-15'
The difference of these two datetimes in Days should be quivalent to 105.
The calculation works as follows: For every full month add 30 days, for the rest add the days till the date is achieved.
I could program this, but it would be an enormous SQL-statement, which I find find kinda ugly.
Is there any simple solution for this, like a built-in function or something short?
Thanks in advance.
Does this do the trick?
;with dates as
(
SELECT
CAST ('2011-01-01' AS DATETIME) as start_date
,CAST('2011-04-15' AS DATETIME) as end_date
)
SELECT
start_date
,end_date
,CASE WHEN DATEDIFF(MM,start_date,end_date) = 0 THEN DAY(end_date) - DAY(start_date)
WHEN DAY(start_date) = 1 THEN (30 * (DATEDIFF(MM,start_date,end_date))) + DAY(end_date)
WHEN DAY(start_date) <> 1 THEN 30 * DATEDIFF(MM,start_date,end_date) + (DAY(end_date) - DAY(start_date))
END AS gap_in_days
FROM dates
Short Answer
There's no built in function, but you could pretty easily create your own to handle converting a datetime to an int. From there, the SQL you would have to write would be trivial.
Long Answer
There's no built in function that will do this, probably because every month doesn't have 30 days. :)
You can start with this:
DECLARE #start DATETIME = '2011-01-01',
#end DATETIME = '2011-04-15'
DECLARE #endConverted INT
SELECT #endConverted = DATEPART(month, #end) * 30
+ CASE
WHEN DATEPART(DAY, #end) <= 30
THEN datepart(DAY, #end)
ELSE 30
END
DECLARE #startConverted INT
SELECT #startConverted = DATEPART(MONTH, #start) * 30
+ CASE
WHEN DATEPART(DAY, #start) <= 30
THEN DATEPART(DAY, #start)
ELSE 30
END
SELECT #endConverted - #startConverted
This isn't beautiful SQL, but it works. Note that it returns 104 (because 15 days - 1 day = 14 days), but simple enough to tack on a + 1 to the end of the final select if you want to handle the boundry days differently.
Note that the math here could pretty easily be moved into a function, which would allow you to clean your SQL up. Let's assume you created a function called GetDateTimeAsInt which holds the math; your SQL could be as simple as
DECLARE #start INT = GetDateTimeAsInt('2011-01-01'),
#end INT = GetDateTimeAsInt('2011-04-15')
SELECT #end - #start -- may need to add 1 here
In my testing, this seems to work. It will return the same result as the DATEDIFF function for the date range you specify in your post, but this is because there are 2 days with 31 days and 1 day with 28, so effectively, Jan - April have 30 days each. If you use it with a wider date range, you'll begin to get different results with my code vs. the DATEDIFF function.
Hope this helps.
I use PERIODDIFF. To get the year and the month of the date, I use the function EXTRACT:
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
T-sql
SELECT DATEDIFF(dd, "2011-01-01","2011-04-15")