问题
I have two tables below. I want to count the number of days, Monday-Friday only between Hire_dt and end of calendar month the hire date falls under.
TableA
Hire_DT Id
09/26/2018 1
TableCalendar:
Date WorkDay(M-F) EOM WorkDay
09/26/2018 Wednesday 9/30/2018 1
09/27/2018 Thursday 09/30/2018 1
09/28/2018 Friday 09/30/2018 1
09/29/2018 Saturday 09/30/2018 0
09/30/2018 Sunday 09/30/2018 0
Expected Results
Hire_dt WorkDaysEndMonth WorkDaysEndMonth --counting hire_dt
09/26/2018 2 3
回答1:
Here is one way to do the calculation - WITHOUT using a calendar table. The only input data is what comes from your first table (ID and HIRE_DATE), which I included in a WITH clause (not part of the query that answers your question!). Everything else is calculated. I show how to compute the number of days INCLUDING the hire date; if you don't need that, subtract 1 at the end.
TRUNC(<date>, 'iw')
is the Monday of the week of <date>
. The query computes how many days are in the EOM week, between Monday and EOM, but no more than 5 (in case EOM may be a Saturday or Sunday). It does a similar calculation for HIRE_DATE, but it counts the days from Monday to HIRE_DATE excluding HIRE_DATE. The last part is adding 5 days for each full week between the Monday of HIRE_DATE and the Monday of EOM.
with
sample_data(id, hire_date) as (
select 1, to_date('09/26/2018', 'mm/dd/yyyy') from dual union all
select 2, to_date('07/10/2018', 'mm/dd/yyyy') from dual
)
select id, to_char(hire_date, 'Dy mm/dd/yyyy') as hire_date,
to_char(eom, 'Dy mm/dd/yyyy') as eom,
least(5, eom - eom_mon + 1) - least(5, hire_date - hire_mon)
+ (eom_mon - hire_mon) * 5 / 7 as workdays
from (
select id, hire_date, last_day(hire_date) as eom,
trunc(hire_date, 'iw') as hire_mon,
trunc(last_day(hire_date), 'iw') as eom_mon
from sample_data
)
;
ID HIRE_DATE EOM WORKDAYS
---------- ----------------------- ----------------------- ----------
1 Wed 09/26/2018 Sun 09/30/2018 3
2 Tue 07/10/2018 Tue 07/31/2018 16
回答2:
You may use the following routine ( where last_day
function is a great contributor ):
SQL> alter session set NLS_TERRITORY="AMERICA";
SQL> create table TableA( ID int, Hire_DT date );
SQL> insert into TableA values(1,date'2018-09-26');
SQL> select sum(case when mod(to_char(myDate,'D'),7) <= 1 then 0 else 1 end )
as "WorkDaysEndMonth"
from
(
select Hire_DT + level - 1 myDate
from TableA
where ID = 1
connect by level <= last_day(Hire_DT) - Hire_DT + 1
);
WorkDaysEndMonth
----------------
3
P.S. integer value comes from to_char(<date>,'D')
depends on the NLS_TERRITORY
setting. Here I used AMERICA
for which Saturday
is the 7th
and Sunday
is the 1st
day, while for UNITED KINGDOM
(or my country TURKEY
) setting those are 6th
and 7th
respectively.
Rextester Demo
来源:https://stackoverflow.com/questions/52977200/count-days-between-two-segments