Count days between two segments

☆樱花仙子☆ 提交于 2020-01-06 08:03:58

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!