sql跳过非工作日(周末和节假日)
简介:场景1:基于开始日期和工期,推算结束日期。 场景2:基于开始日期和结束日期,计算工期 注:需要自己做界面维护工作日表(s_WorkDay)和节假日表(s_SpecialDay)
涉及到的数据表
IF OBJECT_ID('s_WorkDay') IS NULL
BEGIN
CREATE TABLE s_WorkDay([Monday] [TINYINT]
,[Tuesday] [TINYINT]
,[Wednesday] [TINYINT]
,[Thursday] [TINYINT]
,[Friday] [TINYINT]
,[Saturday] [TINYINT]
,[Sunday] [TINYINT]
)
END
GO IF OBJECT_ID('s_SpecialDay') IS NULL
BEGIN
CREATE TABLE s_SpecialDay([SpecialDayGUID] [UNIQUEIDENTIFIER] PRIMARY KEY CLUSTERED NOT NULL
,[BeginDate] [DATETIME]
,[EndDate] [DATETIME]
,[IsWorkDay] [TINYINT]
,[Remarks] [VARCHAR](200)
)
END
GO
场景1:根据开始日期和工期,计算结束日期
--根据开始日期推出结束日期 IF EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[fn_GetEndDate]') AND xtype IN ( N'FN', N'IF', N'TF' ) ) DROP FUNCTION [dbo].[fn_GetEndDate] GO CREATE FUNCTION fn_GetEndDate ( @date DATETIME,@Duration INT ) RETURNS DATETIME AS BEGIN DECLARE @Edate DATETIME DECLARE @IsAdd INT SET @Edate=@date SET @Duration=@Duration-1 DECLARE @NoWorkDay TABLE(iDay int) --非工作日枚举 INSERT INTO @NoWorkDay(iDay) SELECT * FROM dbo.fn_NoWorkDay() WHILE ( @Duration > 0 ) BEGIN SET @IsAdd=0 --默认往后+1 SET @Edate=DATEADD(day, 1, @Edate) --如果非工作日,重复循环,否则跳下一步 IF EXISTS( SELECT TOP 1 1 FROM s_workDay WHERE DATEPART(weekday, @Edate) NOT IN (SELECT * FROM @NoWorkDay)) BEGIN SET @IsAdd=1 SET @Duration = @Duration - 1 END --如果当前日期在特殊非工作日中,则不跳 IF EXISTS( SELECT TOP 1 1 FROM s_SpecialDay WHERE (@Edate BETWEEN begindate AND enddate) AND IsWorkDay=0 AND @IsAdd=1) BEGIN SET @Duration = @Duration + 1 END --如果当前日期在特殊工作日中,则跳1 IF EXISTS( SELECT TOP 1 1 FROM s_SpecialDay WHERE (@Edate BETWEEN begindate and enddate) AND IsWorkDay=1 AND @IsAdd=0) BEGIN SET @Duration = @Duration -1 END END RETURN @Edate END GO
场景2:根据两个日期,计算工期
--计算工期 IF EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[fn_GetDuration]') AND xtype IN ( N'FN', N'IF', N'TF' ) ) DROP FUNCTION [dbo].[fn_GetDuration] GO CREATE FUNCTION fn_GetDuration(@BeginDate DATETIME,@EndDate DATETIME) RETURNS INT AS BEGIN DECLARE @iCount INT --A:取出常规工作日 SELECT @iCount = ISNULL(dbo.fn_GetWorkDay(@BeginDate, @EndDate), 0) --B:减去特殊非工作日 SELECT @iCount = @iCount - ISNULL(SUM(dbo.fn_GetWorkDay(CASE WHEN begindate < @BeginDate THEN @BeginDate ELSE begindate END, CASE WHEN enddate > @EndDate THEN @EndDate ELSE enddate END)), 0) FROM s_SpecialDay WHERE isworkday = 0 AND SpecialDayGUID NOT IN ( SELECT SpecialDayGUID FROM s_SpecialDay WHERE ( begindate > @EndDate AND enddate > @EndDate ) OR ( begindate < @BeginDate AND enddate < @BeginDate ) ) ----C:加上特殊工作日 SELECT @iCount = @iCount + ISNULL(SUM(DATEDIFF(dd, CASE WHEN begindate < @BeginDate THEN @BeginDate ELSE begindate END, CASE WHEN enddate > @EndDate THEN @EndDate ELSE enddate END) - dbo.fn_GetWorkDay(CASE WHEN begindate < @BeginDate THEN @BeginDate ELSE begindate END, CASE WHEN enddate > @EndDate THEN @EndDate ELSE enddate END)), 0) FROM s_SpecialDay WHERE isworkday = 1 AND SpecialDayGUID NOT IN ( SELECT SpecialDayGUID FROM s_SpecialDay WHERE ( begindate > @EndDate AND enddate > @EndDate ) OR ( begindate < @BeginDate AND enddate < @BeginDate ) ) RETURN @iCount END GO
需要用到的函数
IF EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[fn_NoWorkDay]') AND xtype IN ( N'FN', N'IF', N'TF' ) ) DROP FUNCTION [dbo].[fn_NoWorkDay] GO --输出非工作日 CREATE FUNCTION fn_NoWorkDay() RETURNS @NoWorkDay TABLE ( iDay INT ) AS BEGIN INSERT INTO @NoWorkDay ( iDay ) SELECT 2 FROM s_WorkDay WHERE Monday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 3 FROM s_WorkDay WHERE Tuesday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 4 FROM s_WorkDay WHERE Wednesday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 5 FROM s_WorkDay WHERE Thursday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 6 FROM s_WorkDay WHERE Friday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 7 FROM s_WorkDay WHERE Saturday = 0 INSERT INTO @NoWorkDay ( iDay ) SELECT 1 FROM s_WorkDay WHERE Sunday = 0 RETURN END Go --计算工作日 IF EXISTS ( SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[fn_GetWorkDay]') AND xtype IN ( N'FN', N'IF', N'TF' ) ) DROP FUNCTION [dbo].[fn_GetWorkDay] GO CREATE FUNCTION fn_GetWorkDay(@BeginDate DATETIME,@EndDate DATETIME) RETURNS INT AS BEGIN DECLARE @NoWorkDay TABLE(iDay int) --非工作日枚举 INSERT INTO @NoWorkDay(iDay) SELECT * FROM fn_NoWorkDay() DECLARE @i INT,@iCount INT SET @iCount=0 SET @i = DATEDIFF(day, @BeginDate, @EndDate) WHILE ( @i >= 0 ) BEGIN --如果开始日期往后顺延,遇到非工作日,则不计数 IF EXISTS( SELECT TOP 1 1 FROM s_workDay WHERE DATEPART(weekday, @BeginDate) NOT IN (SELECT * FROM @NoWorkDay)) BEGIN SET @iCount=@iCount+1 END SET @BeginDate=DATEADD(day, 1, @BeginDate) SET @i = @i - 1 END RETURN @iCount END go
sql跳过非工作日(周末和节假日)的更多相关文章
- SQL计算时间差并排除周末
SQL计算时间差并排除周末 CREATE FUNCTION DI_FN_GET_WorkDay (@begin DATETIME , @end DATETIME ) RETURNS int BEGIN ...
- java获取n个工作日后的日期, 排除周末和节假日(顺延)
一.写在前面 需求: 工作需要获取n个工作日后的日期, 需要排除weekend和holiday, holiday存在数据库中, 存入的形式是一个节日有起始日期和截止日期(以下文中有关于节假日的表截图) ...
- 写sql语句分别按日,星期,月,季度,年统计
--写sql语句分别按日,星期,月,季度,年统计销售额 --按日 ' group by day([date]) --按周quarter ' group by datename(week,[date]) ...
- 数据库:sql语句分别按日,按周,按月,按季统计金额
如: 表:consume_record 字段:consume (money类型) date (datetime类型) 请问怎么写四条sql语句分别按日,按周,按月,按季统计消费总量. 如:1月 120 ...
- Oracle笔记 八、PL/SQL跳转/判断/循环语句块
--goto跳转语句 --在goto 后,跳转到相应的语句,然后执行该语句和后面所有语句 begin dbms_output.put_line('goto开始了'); goto c; --不被执行 d ...
- 一条SQL语句中算日销售额和月销售额
刚刚做项目的时候用到的 用户表:用户ID,用户名,余额 流水表:时间,用户ID,用户名,类型(0充值,1消费),变更金额 现在要查每个用户的日销售额和月销售额,本来最简单的方法是先把所有用户查出来,然 ...
- SQL实现一年中每个日期剔除节假日和星期天之后的五个日期是多少
最近公司OA系统的需求,实现一年中每个日期剔除节假日和星期天之后的五个日期是几号,每个日期都要跳过节假日和星期天,当时是真的慌了,郁闷了一天,后来半夜忽然来灵感,想想还是可以实现. 需要做一张节假日的 ...
- c# 计算两日期的工作时间间隔(排除非工作日)及计算下一个工作时间点.
一个日期段如工作时间为 8:00 至 17:00 public class TimeHelper { /// <summary> /// 计算时间间隔 /// </summary&g ...
- SQL Server误区30日谈 第26天 SQL Server中存在真正的“事务嵌套”
误区 #26: SQL Server中存在真正的“事务嵌套”错误 嵌套事务可不会像其语法表现的那样看起来允许事务嵌套.我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQL Serve ...
随机推荐
- HDU 3911 线段树区间合并
北京赛区快了,准备袭击数据结构和图论.倒计时 18天,线段树区间合并.维护一个最长连续.. 题意:给一个01串,以下有一些操作,问区间最长的连续的1的个数 思路:非常裸的线段树区间合并 #includ ...
- OpenCV学习笔记09--通过cvPtr2D或指针算法绘制图形
练习:创建一个1000*1000的三通道图像,将其元素所有置0.以(200,50)和(400,200)为顶点绘制一个绿色平面 我们能够用两种方法来实现这一功能,一个是使用cvPtr2D,可是因为使用了 ...
- vue15 自定义元素指令、标签指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- zzulioj--1089--make pair(dfs+模拟)
1809: make pair Time Limit: 1 Sec Memory Limit: 128 MB Submit: 60 Solved: 44 SubmitStatusWeb Board ...
- poj--1149--PIGS(最大流经典建图)
PIGS Time Limit: 1000MS Memory Limit: 10000KB 64bit IO Format: %I64d & %I64u Submit Status D ...
- jasperreport 追加新报表(2)
用ireport做好模版后,如果要新加一个打印页,如果是新手,直接修改模版应该是理想情况, 可是什么数据源 feild,parameter,var,subreport ,还有路径, 真的可以让一个人疯 ...
- c# 引用ConfigurationManager 类
c#添加了Configuration;后,竟然找不到 ConfigurationManager 这个类,后来才发现:虽然引用了using System.Configuration;这个包,但是还是不行 ...
- node.js状态码
100——客户必须继续发出请求101——客户要求服务器根据请求转换HTTP协议版本200——交易成功201——提示知道新文件的URL202——接受和处理.但处理未完成203——返回信息不确定或不完整2 ...
- iscsi共享存储的简单配置和应用
1.环境介绍 SCSI(Small Computer System Interface)是块数据传输协议,在存储行业广泛应用,是存储设备最基本的标准协议.从根本上说,iSCSI协议是一种利用IP网络来 ...
- b模式处理文件
1.读 f=open('cheng','rb') date=f.read() print(date.decode()) 2.写 f=open('cheng','ab') f.write('chengz ...