Oracle计算某日期段内排除周六日之后的天数(请假,工作日,日期型)

因为本人不是主要从事Oracle等大数据操作方向,所以对于SQL语句了解并不专业,本文主要用于记录自己的使用心得,以及为广大网友提供思路,如果不喜欢我的解析和讲解可以直接跳过,拿走你觉得有用的SQL。

如题,最近在项目中有个计算请假天数的SQL语句,大体的需求就是:

给出了员工请假的起止日期,根据查询条件(查询日期起,查询日期止),计算员工请假的起止日期在条件中实际的请假天数(关键是员工请假表中有员工录入的请假天数,这点不太人性化)。

例如:某员工的请假起止日期为:2019/07/08,2019/07/17,查询日期条件为:2019/07/01,2019/07/31,则该员工在查询时间段中请假为8天。这是一种简单的情况举例,还会有其他几种情况,在SQL语句中体现。

第一点:我们需要知道最重要的一点,需要判断员工请假日期是否与查询条件日期之间存在交集。如果不存在,说明不需要去处理该员工请假的记录。

第二点:如果两段日期存在交集,说明这些记录是需要我们去处理的。我简单分为了以下3种情况(不知道是否考虑全面)。

              第一种情况:员工请假日期包含查询条件日期。举个例子,员工请假日期:19/07/01至19/07/31,查询条件日期:19/07/15至19/07/21。这种情况我们不需要使用员工请假日期,可以直接使用查询条件日期进行计算。

              第二种情况:员工请假日期在查询条件日期内。这种情况比较好理解,员工请假日期:19/07/15至19/07/21,查询条件日期:19/07/01至19/07/31。这种情况我们使用员工请假日期进行计算就可以。

              第三种情况:员工请假日期起到请假日期止之间有一段时间与查询条件日期有交集。这种情况较为复杂,需要有两种处理方式。First,员工请假日期后面的部分与查询条件日期之间有交集,举例:员工请假日期:19/01/01至19/07/21,查询条件日期:19/07/01至19/07/31,交集为查询条件日期起(19/07/01)到员工请假日期止(19/07/21);Second,员工请假日期前面的部分与查询条件日期之间有交集,举例:员工请假日期:19/07/01至19/10/22,查询条件日期:19/07/01至19/07/31,交集为员工请假日期起(19/07/01)到查询条件日期止(19/07/31)。

说实话我觉得就很复杂,为啥会有这种鬼需求。让我在网上搜了好久,没有找到一点有用的。

继续,解析完这几种情况,开始进入SQL语句。

因为是计算排除周六日之后的工作日,因此,在网查到了这样一个SQL(日期起止自己改一个时间,可以直接使用测试):

select (trunc(to_date(日期止,'yyyy-mm-dd') - to_date(日期起,'yyyy-mm-dd')) - ((
   case WHEN (8 - to_number(to_char(to_date(日期起,'yyyy-mm-dd'),'D'))) > trunc(to_date(日期止,'yyyy-mm-dd') - to_date(日期起,'yyyy-mm-dd')) + 1 THEN 0
         ELSE trunc((trunc(to_date(日期止,'yyyy-mm-dd') - to_date(日期起,'yyyy-mm-dd')) - (8 - to_number(to_char(to_date(日期起,'yyyy-mm-dd'),'D'))))/7) END) + (
   case WHEN mod(8 - to_char(to_date(日期起,'yyyy-mm-dd'), 'D'), 7) > trunc(to_date(日期止,'yyyy-mm-dd') - to_date(日期起,'yyyy-mm-dd')) - 1 THEN 0
         ELSE trunc((trunc(to_date(日期止,'yyyy-mm-dd') - to_date(日期起,'yyyy-mm-dd')) - (mod(8 - to_char(to_date(日期起,'yyyy-mm-dd'),'D'),7) + 1))/7) + 1  END))
	) as workingdays
from dual

如果读者想深入了解这个SQL,请读者自己解析,我不是专业的,担心解析出错(其实就是懒得看了)。反正倒是好使。

然后我的员工请假SQL语句如下:(文字有点多,可以复制到navicat里面查找替换。其中员工请假天数是员工自己填的,主要是针对有员工请假为0.5之类的小数的情况。这里的员工请假日期起止为表中字段)

SELECT yguuid,username,
sum(CASE WHEN 员工请假日期起 <= TO_DATE(查询条件日期起,'YYYY-MM-DD') and 员工请假日期止 >= TO_DATE(查询条件日期止,'YYYY-MM-DD') THEN (
    trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - ((
      case WHEN (8 - to_number(to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'))) > trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) + 1 THEN 0
        ELSE trunc((trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) -(8 - to_number(to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'))))/7) END) + (
      case WHEN mod(8 - to_char(to_date(查询条件日期起,'yyyy-mm-dd'), 'D'), 7) > trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - 1 THEN 0
        ELSE trunc((trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - (mod(8 - to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'),7) + 1))/7) + 1  END))
)
WHEN 员工请假日期起 >= TO_DATE(查询条件日期起,'YYYY-MM-DD') and 员工请假日期止 <= TO_DATE(查询条件日期止,'YYYY-MM-DD') THEN 员工请假天数 
WHEN 员工请假日期起 <= TO_DATE(查询条件日期起,'YYYY-MM-DD') and 员工请假日期止 <= TO_DATE(查询条件日期止,'YYYY-MM-DD') THEN (
    trunc(to_date(to_char(员工请假日期止,'yyyy-mm-dd'),'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - ((
      case WHEN (8 - to_number(to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'))) > trunc(to_date(to_char(员工请假日期止,'yyyy-mm-dd'),'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) + 1 THEN 0
        ELSE trunc((trunc(to_date(to_char(员工请假日期止,'yyyy-mm-dd'),'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) -(8 - to_number(to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'))))/7) END) + (
      case WHEN mod(8 - to_char(to_date(查询条件日期起,'yyyy-mm-dd'), 'D'), 7) > trunc(to_date(to_char(员工请假日期止,'yyyy-mm-dd'),'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - 1 THEN 0
        ELSE trunc((trunc(to_date(to_char(员工请假日期止,'yyyy-mm-dd'),'yyyy-mm-dd') - to_date(查询条件日期起,'yyyy-mm-dd')) - (mod(8 - to_char(to_date(查询条件日期起,'yyyy-mm-dd'),'D'),7) + 1))/7) + 1  END))
)
WHEN 员工请假日期起 >= TO_DATE(查询条件日期起,'YYYY-MM-DD') and 员工请假日期止 >= TO_DATE(查询条件日期止,'YYYY-MM-DD') THEN (
    trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd')) - ((
      case WHEN (8 - to_number(to_char(to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd'),'D'))) > trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd')) + 1 THEN 0
        ELSE trunc((trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd')) -(8 - to_number(to_char(to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd'),'D'))))/7) END) + (
      case WHEN mod(8 - to_char(to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd'), 'D'), 7) > trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd')) - 1 THEN 0
        ELSE trunc((trunc(to_date(查询条件日期止,'yyyy-mm-dd') - to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd')) - (mod(8 - to_char(to_date(to_char(员工请假日期起,'yyyy-mm-dd'),'yyyy-mm-dd'),'D'),7) + 1))/7) + 1  END))
)
END) qjts 
from xmgl_ygqjxx WHERE (员工请假日期起 <= TO_DATE(查询条件日期止,'YYYY-MM-DD') and 员工请假日期止 >= TO_DATE(查询条件日期起,'YYYY-MM-DD')) GROUP BY yguuid,username

如有疑问请留言。。。。

猜你喜欢

转载自blog.csdn.net/FV8023/article/details/95194067