PL SQL Retirement function - plsql

I need a help on this function. The code has no error but it keeps returning the same result, that the value from of the second condition/statement.
This is how it suppose to work:
If employees age at hire date (DOFA) is less than or equals to 25 the retirement date is 35 years from hire date. Otherwise retirement date is when employees age is 60
create or replace function EDOR_FUNCTION
(DOFA in date, DOB in date)
return date
is
new_edor_date date;
begin
if
DOFA - DOB <= 25 then new_edor_date := add_months(DOFA, 35*12);
else
new_edor_date := add_months(DOB, 60*12);
end if;
return new_edor_date;
end;

Your condition subtracts one date from another. This gives the number of days between the two, not the number of years.
months_between() gives the number of months between two dates. Multiply by twelve to get number of years
if months_between(DOFA , DOB) <= (25*12) then
new_edor_date := add_months(DOFA, 35*12);
else
new_edor_date := add_months(DOB, 60*12);
end if;

Related

Impala - Working hours between two dates in impala

I have two time stamps #starttimestamp and #endtimestamp. How to calculate number of working hours between these two
Working hours is defined below:
Mon- Thursday (9:00-17:00)
Friday (9:00-13:00)
Have to work in impala
think i found a better solution.
we will create a series of numbers using a large table. You can get a time dimension type table too. Make it doenst get truncated. I am using a large table from my db.
Use this series to generate a date range between start and end date.
date_add (t.start_date,rs.uniqueid) -- create range of dates
join (select row_number() over ( order by mycol) as uniqueid -- create range of unique ids
from largetab) rs
where end_date >=date_add (t.start_date,rs.uniqueid)
Then we will calculate total hour difference between the timestamp using unix timestamp considering date and time.
unix_timestamp(endtimestamp - starttimestamp )
Exclude non working hours like 16hours on M-T, 20hours on F, 24hours on S-S.
case when dayofweek ( dday) in (1,7) then 24
when dayofweek ( dday) =5 then 20
else 16 end as non work hours
Here is complete SQL.
select
end_date, start_date,
diff_in_hr - sum(case when dayofweek ( dday) in (1,7) then 24
when dayofweek ( dday) =5 then 20
else 16 end ) total_workhrs
from (
select (unix_timestamp(end_date)- unix_timestamp(start_date))/3600 as diff_in_hr , end_date, start_date,date_add (t.start_date,rs.uniqueid) as dDay
from tdate t
join (select row_number() over ( order by mycol) as uniqueid from largetab) rs
where end_date >=date_add (t.start_date,rs.uniqueid)
)rs2
group by 1,2,diff_in_hr

Function to generate random date from period [duplicate]

I have this anonymous block:
DECLARE
V_DATA DATE;
BEGIN
V_DATA := '01-GEN-2000';
HR.STATISTICHE.RATINGOPERATORI (V_DATA);
COMMIT;
END;
but I would to generate the date in a random way. How can I do?
You can generate random dates between two dates ,as displayed in the query below .Random Dates are generated between 1-jan-2000 and 31-dec-9999
SELECT TO_DATE(
TRUNC(
DBMS_RANDOM.VALUE(TO_CHAR(DATE '2000-01-01','J')
,TO_CHAR(DATE '9999-12-31','J')
)
),'J'
) FROM DUAL;
OR you can use
SELECT TO_DATE (
TRUNC (
DBMS_RANDOM.VALUE (2451545, 5373484)
)
, 'J'
)
FROM DUAL
In the above example ,the first value is 01-Jan-2000 and the second value id 31-dec-9999
To generate random date you can use
select to_date('2010-01-01', 'yyyy-mm-dd')+trunc(dbms_random.value(1,1000)) from dual
or for random datetime
select to_date('2010-01-01', 'yyyy-mm-dd')+dbms_random.value(1,1000) from dual
If you want to see it's logic, you can also use this code.
create or replace procedure genDate(result out nvarchar2) IS
year number;
month number;
day number;
Begin
year:=FLOOR(DBMS_RANDOM.value(2000,2100));
month:=FLOOR(DBMS_RANDOM.value(1,12));
IF month=2 and (year/4)=0 and (year/100)!=0 then
day:=FLOOR(DBMS_RANDOM.value(1,29));
ELSIF month=2 or (year/100)=0 then
day:=FLOOR(DBMS_RANDOM.value(1,28));
ELSIF MOD(month,2)=1 then
day:=FLOOR(DBMS_RANDOM.value(1,31));
ELSIF MOD(month,2)=0 and month!=2 then
day:=FLOOR(DBMS_RANDOM.value(1,30));
END IF;
result:=month||'-'||day||'-'||year;
End;
here is one more option to generate date going back from now where 365 - days quanitity to move back from today, 'DD.MM.YYYY'- mask
to_char(sysdate-dbms_random.value()*365, 'DD.MM.YYYY')
I needed to generate employee data for testing. Each employee needed a date of birth that put them between 16 and 65 years of age, and a date of hire sometime between their 16th birthday and SYSDATE. Here's how...
FUNCTION randomDateInRange(alpha IN DATE, omega IN DATE) RETURN DATE IS
BEGIN
RETURN alpha + DBMS_RANDOM.VALUE(0, omega - alpha);
END;
...and then, to use this function...
-- an employee can be any age from 16 to 65 years of age
DoB := randomDateInRange(
SYSDATE - INTERVAL '65' YEAR,
SYSDATE - INTERVAL '16' YEAR
);
-- an employee could have been hired any date since their sixteenth birthday
DoH := randomDateInRange(
DoB + INTERVAL '16' YEAR,
SYSDATE
);

Get DateTime corresponding to last Thu or Fri or Mon etc in SQL Server 2012

I have a certain DATETIME value, and I would like to get the DATETIME value for a given weekday 'n' (where n is an integer from 1 thru to 7) that is just before the given date.
Question: How would I do this given a value for currentDate and a value for lastWeekDay?
For example, if given date is 06/15/2015 in mm/dd/yyyy format, then what is the date for a weekday of 6 that came just before 06/15/2015. In this example, given date is on Monday and we want the date for last Friday (i.e. weekday =6).
declare #currentDate datetime, #lastWeekDay int;
set #currentDate = getdate();
set #lastWeekDay = 6;--this could be any value from 1 thru to 7
select #currentDate as CurrentDate, '' as LastWeekDayDate --i need to get this date
UPDATE 1
In addition to the excellent answer by Anon, I also found an alternate way of doing it, which is as given below.
DECLARE #currentWeekDay INT;
SET #currentWeekDay = DATEPART(WEEKDAY, #currentDate);
--Case 1: when current date week day > lastWeekDay then subtract
-- the difference between the two weekdays
--Case 2: when current date week day <= lastWeekDay then go back 7 days from
-- current date, and then add (lastWeekDay - currentWeekDay)
SELECT
#currentDate AS CurrentDate,
CASE
WHEN #currentWeekDay > #lastWeekDay THEN DATEADD(DAY, -1 * ABS(CAST(#lastWeekDay AS INT) - CAST(#currentWeekDay AS INT)), #currentDate)
ELSE DATEADD(DAY, #lastWeekDay - DATEPART(WEEKDAY, DATEADD(DAY, -7, #currentDate)), DATEADD(DAY, -7, #currentDate))
END AS LastWeekDayDate;
Calculate how many days have passed since a fixed date, modulo 7, and subtract that from the input date. The magic number '5' is because Date Zero (1900-01-01) is a Monday. Shifting that forward 5 days makes the #lastWeekDay range [1..7] map to the range of weekdays [Sunday..Saturday].
SELECT DATEADD(day,-DATEDIFF(day,5+#lastWeekDay,#currentDate)%7,#currentDate)
I avoid the DATEPART(weekday,[...]) function because of SET DATEFIRST

how to get last working day from date if selected date is monday in oracle

i want to make a function in oracle database. in witch i want to get 1 day previous date from selected date, if selected date is "Monday" then i want to select date of "Friday" as previous date as it is last working day of week.
Try this:
CREATE OR REPLACE FUNCTION PREVIOUS_WORKING_DAY(pDate IN DATE)
RETURN DATE
IS
strDay_of_week VARCHAR2(50);
dtPrev DATE;
BEGIN
strDay_of_week := TRIM(TO_CHAR(pDate, 'DAY'));
CASE strDay_of_week
WHEN 'MONDAY' THEN
dtPrev := TRUNC(pDate) - INTERVAL '3' DAY;
WHEN 'SUNDAY' THEN
dtPrev := TRUNC(pDate) - INTERVAL '2' DAY;
ELSE
dtPrev := TRUNC(pDATE) - INTERVAL '1' DAY;
END CASE;
RETURN dtPrev;
END PREVIOUS_WORKING_DAY;
Share and enjoy.

oracle pl/sql: datepart () function for weekend exclusion

can i use to_number(to_char()) function in order to exclude all the weekends from a range of dates?
For instance, there are two date columns in my table such as start and finish (in the form of '06/06/2011 10:00:00 am'), and i want to estimate the duration of finish-start excluding Saturdays and Sundays.
If I understand you right you want to calculate the difference between two dates, but exclude the 2 days of each weekend in the range from the result. Is that correct?
If this is what you want the below code should work with the following assumptions:
I am assume start and end will not be on weekends.
I am not validating that end is before start.
Basically its just a matter of working out how many weekends are in the date range. So obviously there's one weekend per 7 days. Then we just have to check if the range wraps around a weekend, and if so add one more.
FUNCION dateDiff( dt_start DATE, dt_end DATE ) RETURN NUMBER
IS
raw_diff NUMBER;
weekends NUMBER;
BEGIN
raw_diff := dt_end - dt_start;
weekends := TRUNC( raw_diff / 7 );
IF( ( dt_start - TRUNC( dt_start, 'DAY' ) )
> ( dt_end - TRUNC( dt_end , 'DAY' ) ) )
THEN
weekends := weekends + 1;
END IF;
RETURN raw_diff - ( weekends * 2 );
END;

Resources