问题

给定两个日期,求它们之间(包括这两个日期本身)有多少个“工作”日。例如,如果1月10日是星期一,1月11日是星期二,由于这两个日期是典型的工作日,所以两个日期之间的工作日数是2。对于这个问题,“工作日”定义为非周六/周日的日子。

解决方案

下面的例子计算BLAKE 和JONES 的HIREDATE(聘用日期)之间的工作日数。要确定两个日期之间的工作日数,可以使用基干表,对两个日期(其中包括起始日期和结束日期)之间的每一天都返回一行。此后,计算工作日数只是数一下返回的日期中非周六/周日的数目。

注意:    如果也想去掉假期,则可以创建一个HOLIDAYS表。然后引入NOT IN前缀,就能够从解决方案中去掉HOLIDAYS 中列出的日子。

DB2

使用基干表T500,能够生成两个日期之间包含的行数(表示天数),然后,对非周末的所有日期计数。使用DAYNAME 函数可返回每个日期是星期几。例如:

1  select sum(case when dayname(jones_hd+t500.id day -1 day)

2                    in ( 'Saturday','Sunday' )

3                  then 0 else 1

4             end) as days

5    from (

6  select max(case when ename = 'BLAKE'

7                  then hiredate

8             end) as blake_hd,

9         max(case when ename = 'JONES'

10                  then hiredate

11             end) as jones_hd

12    from emp

13   where ename in ( 'BLAKE','JONES' )

14         ) x,

15         t500

16   where t500.id <= blake_hd-jones_hd+1

MySQL

使用基干表T500能够生成两个日期之间包含的行数(天数),然后,对非周末的所有日期计数。使用DATE_ADD函数可以给每个日期增加天数;使用DATE_FORMAT函数判定每个日期是星期几:

1  select sum(case when date_format(

2                          date_add(jones_hd,

3                                   interval t500.id-1 DAY),'%a')

4                    in ( 'Sat','Sun' )

5                  then 0 else 1

6             end) as days

7    from (

8  select max(case when ename = 'BLAKE'

9                  then hiredate

10             end) as blake_hd,

11         max(case when ename = 'JONES'

12                  then hiredate

13             end) as jones_hd

14    from emp

15   where ename in ( 'BLAKE','JONES' )

16         ) x,

17         t500

18   where t500.id <= datediff(blake_hd,jones_hd)+1

Oracle

使用基干表T500能够生成两个日期之间包含的行数(天数),然后,对非周末的所有日期计数。使用TO_CHAR函数确定每个日期是星期几:

1  select sum(case when to_char(jones_hd+t500.id-1,'DY')

2                    in ( 'SAT','SUN' )

3                  then 0 else 1

4             end) as days

5    from (

6  select max(case when ename = 'BLAKE'

7                  then hiredate

8             end) as blake_hd,

9         max(case when ename = 'JONES'

10                  then hiredate

11             end) as jones_hd

12    from emp

13   where ename in ( 'BLAKE','JONES' )

14         ) x,

15         t500

16   where t500.id <= blake_hd-jones_hd+1

PostgreSQL

使用基干表T500能够生成两个日期之间包含的行数(天数),然后,对非周末的所有日期计数。使用TO_CHAR函数确定每个日期是星期几:

1  select sum(case when trim(to_char(jones_hd+t500.id-1,'DAY'))

2                    in ( 'SATURDAY','SUNDAY' )

3                  then 0 else 1

4             end) as days

5    from (

6  select max(case when ename = 'BLAKE'

7                  then hiredate

8             end) as blake_hd,

9         max(case when ename = 'JONES'

10                  then hiredate

11             end) as jones_hd

12    from emp

13   where ename in ( 'BLAKE','JONES' )

14         ) x,

15         t500

16   where t500.id <= blake_hd-jones_hd+1

SQL Server

使用基干表T500生成两个日期之间包含的行数(天数),然后,对非周末的所有日期计数。使用DATENAME函数确定每个日期是星期几:

1  select sum(case when datename(dw,jones_hd+t500.id-1)

2                    in ( 'SATURDAY','SUNDAY' )

3                   then 0 else 1

4             end) as days

5    from (

6  select max(case when ename = 'BLAKE'

7                  then hiredate

8             end) as blake_hd,

9         max(case when ename = 'JONES'

10                  then hiredate

11             end) as jones_hd

12    from emp

13   where ename in ( 'BLAKE','JONES' )

14         ) x,

15         t500

16   where t500.id <= datediff(day,jones_hd-blake_hd)+1

讨论

尽管每个RDBMS都需要使用不同的内置函数确定日期名,对每个系统来说,总体解决方案都相同。可以把解决方案分成下面两个步骤:

1.    返回起始日期和结束日期之间的天数(二者均包含在内);

2.    计数除周末以外共有多少天(即行数)。

内联视图X 完成第一步操作。如果检查内联视图X,会注意到,它使用了聚集函数MAX,该函数用于删除NULL。如果对MAX的用法不是很清楚,下面这个例子会有助于读者理解。以下显示了未使用MAX时内联视图X的结果:

select case when ename = 'BLAKE'

then hiredate

end as blake_hd,

case when ename = 'JONES'

then hiredate

end as jones_hd

from emp

where ename in ( 'BLAKE','JONES' )

BLAKE_HD    JONES_HD

----------- -----------

02-APR-1981

01-MAY-1981

如果不使用MAX,会返回两行。而使用MAX,只返回一行,且去掉了NULL:

select max(case when ename = 'BLAKE'

then hiredate

end) as blake_hd,

max(case when ename = 'JONES'

then hiredate

end) as jones_hd

from emp

where ename in ( 'BLAKE','JONES' )

BLAKE_HD    JONES_HD

----------- -----------

01-MAY-1981 02-APR-1981

上述两个日期之间的天数(其中包括两个日期本身)是30。既然两个日期处于一行,那么,下一步就要对这30天 的每一天分别生成一行记录。要返回30天(行),需使用表T500。由于表T500中的每个ID值都比它的前一个值大1,在两个日期中较早的一个 (JONES_HD)上分别加上T500中各行的ID,就可以生成从JONES_HD日期开始直到BLAKE_HD(包括)的连续工作日。其结果如下所示 (使用Oracle语法):

select x.*, t500.*, jones_hd+t500.id-1

from (

select max(case when ename = 'BLAKE'

then hiredate

end) as blake_hd,

max(case when ename = 'JONES'

then hiredate

end) as jones_hd

from emp

where ename in ( 'BLAKE','JONES' )

) x,

t500

where t500.id <= blake_hd-jones_hd+1

BLAKE_HD    JONES_HD            ID JONES_HD+T5

----------- ----------- ---------- -----------

01-MAY-1981 02-APR-1981          1 02-APR-1981

01-MAY-1981 02-APR-1981          2 03-APR-1981

01-MAY-1981 02-APR-1981          3 04-APR-1981

01-MAY-1981 02-APR-1981          4 05-APR-1981

01-MAY-1981 02-APR-1981          5 06-APR-1981

01-MAY-1981 02-APR-1981          6 07-APR-1981

01-MAY-1981 02-APR-1981          7 08-APR-1981

01-MAY-1981 02-APR-1981          8 09-APR-1981

01-MAY-1981 02-APR-1981          9 10-APR-1981

01-MAY-1981 02-APR-1981         10 11-APR-1981

01-MAY-1981 02-APR-1981         11 12-APR-1981

01-MAY-1981 02-APR-1981         12 13-APR-1981

01-MAY-1981 02-APR-1981         13 14-APR-1981

01-MAY-1981 02-APR-1981         14 15-APR-1981

01-MAY-1981 02-APR-1981         15 16-APR-1981

01-MAY-1981 02-APR-1981         16 17-APR-1981

01-MAY-1981 02-APR-1981         17 18-APR-1981

01-MAY-1981 02-APR-1981         18 19-APR-1981

01-MAY-1981 02-APR-1981         19 20-APR-1981

01-MAY-1981 02-APR-1981         20 21-APR-1981

01-MAY-1981 02-APR-1981         21 22-APR-1981

01-MAY-1981 02-APR-1981         22 23-APR-1981

01-MAY-1981 02-APR-1981         23 24-APR-1981

01-MAY-1981 02-APR-1981         24 25-APR-1981

01-MAY-1981 02-APR-1981         25 26-APR-1981

01-MAY-1981 02-APR-1981         26 27-APR-1981

01-MAY-1981 02-APR-1981         27 28-APR-1981

01-MAY-1981 02-APR-1981         28 29-APR-1981

01-MAY-1981 02-APR-1981         29 30-APR-1981

01-MAY-1981 02-APR-1981         30 01-MAY-1981

检查WHERE子句会注意到,对BLAKE_HD和JONES_HD之差进行了加1操作,生成了30行(否则 的话,将生成29行)。另外,还会看到,对外部查询的SELECT列表中的T500.ID进行了减1操作,这是由于ID的起始值为1,而且,对 JONES_HD进行加1操作,会导致从最终结果中减掉JONES_HD。

一旦生成了结果集需要的行数,可以使用CASE表达式“标记”返回的每一天是工作日还是周末(工作日返回1,周末返回0)。最后一步,使用求和函数SUM计算1的个数,以得到最终答案。

Sql确定两个日期之间的工作日数目相关推荐

  1. SQL计算两个日期之间的工作日天数,去除法定节假日和周末

    项目要求:需要计算两个日期之间的工作日天数,包含元旦.五一.十一等法定假日. 网上查询很多SQL函数,最终发现都不太理想,例如国庆放假可能会调休,周末也要上班.所以唯一的解决方案是建立一张工作日时间表 ...

  2. SQL计算两个日期之间的工作日天数

    https://blog.csdn.net/qq_37436998/article/details/85867729 参考这篇文章,先创建数据库,然后通过插入数据库一个函数,这样写SQL的时候就调用这 ...

  3. 计算两个日期之间的工作日(去掉周末和节假日)

    一个贴吧上找到的,整理一下 package com.uphone.commons;import java.text.ParseException; import java.text.SimpleDat ...

  4. sqlserver计算两个日期之间的工作日(剔除周末及法定节假日)

    sqlserver计算两个日期之间的工作日(剔除周末及法定节假日) create function [dbo].[WorkDay] ( @beginday datetime, @endday date ...

  5. oracle 节假日天数,强大的PLSQL - 计算两个日期之间的工作日天数-除去(周末和公共假日...

    用php写了一个函数,实现的功能是 计算两个日期之间的工作日天数-除去(周末和公共假日)写了 300多行的代码,  实现公共假日从文件中读取, 或者从数据库提取, 然后传入两个日期,就能返回想要的结果 ...

  6. SQL计算两个日期之间的工作天数

    if exists (select * from dbo.sysobjects where id = object_id(N'[tb_Holiday]') and OBJECTPROPERTY(id, ...

  7. mysql计算两个日期之间的工作日(可跨年,排除周六日,不排除节日)

    SELECT(floor( days / 7 )* 5 + days % 7 -CASEWHEN 6 BETWEEN wd AND wd + days % 7-1 THEN1 ELSE 0 END - ...

  8. 计算两个日期之间的工作日天数

    计算两个工作日之间的天数 : 利用循环遍历开始时间和结束时间之间的天数,工作日则累计,非工作日跳过,不过如果开始时间和结束时间之间很长,效率可能不高, import java.text.DateFor ...

  9. 计算两个日期之间的工作日

    Go --创建函数(CSDN fredrickhu(小F)提供) CREATE FUNCTION f_WorkDay ( @dt_begin   datetime,     --计算的开始日期 @dt ...

最新文章

  1. 华北计算机研究无人机,飞马D200无人机在华北某环境地调项目中的应用案例
  2. P3758 [TJOI2017]可乐
  3. Model 3车主对FSD套件不满意 德国法院下令特斯拉回购汽车
  4. python中的dict函数什么意思_3分钟搞懂Python中dict函数的含义是什么
  5. MySQL备份与恢复-innobackupex
  6. 毕设题目:Matlab指纹识别
  7. 基于Java的2048小游戏设计
  8. 楼宇自控系统(BA)的设计
  9. 使用Vue+Bootstrap开发在线音乐网站
  10. python数独伪代码回溯法_数独的暴力回溯解法和Python GUI
  11. java中的Int范围
  12. 求二元函数最大值matlab,利用matlab, 二元函数求最大值
  13. ie 启用 java_无法使用带有Java的Selenium2(Webdriver)启动IE浏览器
  14. 如何用天干地支计算年月日时?
  15. 互联网快讯:永辉拟打造数字化零售;猿辅导,掌门教育积极布局素质教育
  16. 数据分类分析--聚类
  17. 财税SaaS行业格局再变,慧算账为何能受资本“偏爱”?
  18. redis之地理位置
  19. 台塑集团获批收购奇梦达
  20. 基于SSM的仓库管理系统(含完整源码+论文)

热门文章

  1. DatePicker选择器-快速实现当日,一周前,半月前等
  2. 关于BOF和 EOF
  3. linux卸载apache服务器,linux下卸载apache
  4. python延时us函数_树莓派高级GPIO库,wiringpi2 for python使用笔记(二)高精度计时、延时函数...
  5. 六神磊磊论唐诗中的敏捷:(二)中唐:把太监撤了就是敏捷
  6. 服务器双向认证 原理,https认证方式以及HTTPS双向认证过程
  7. 装载问题 | 分支限界法(限上界)
  8. 2022 ICML | Pocket2Mol: Efficient Molecular Sampling Based on 3D Protein Pockets
  9. 总结用Java写记事本的过程
  10. C++字符串变量的运算 | 使用+输出两个字符串变量