简介:场景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跳过非工作日(周末和节假日)的更多相关文章

  1. SQL计算时间差并排除周末

    SQL计算时间差并排除周末 CREATE FUNCTION DI_FN_GET_WorkDay (@begin DATETIME , @end DATETIME ) RETURNS int BEGIN ...

  2. java获取n个工作日后的日期, 排除周末和节假日(顺延)

    一.写在前面 需求: 工作需要获取n个工作日后的日期, 需要排除weekend和holiday, holiday存在数据库中, 存入的形式是一个节日有起始日期和截止日期(以下文中有关于节假日的表截图) ...

  3. 写sql语句分别按日,星期,月,季度,年统计

    --写sql语句分别按日,星期,月,季度,年统计销售额 --按日 ' group by day([date]) --按周quarter ' group by datename(week,[date]) ...

  4. 数据库:sql语句分别按日,按周,按月,按季统计金额

    如: 表:consume_record 字段:consume (money类型) date (datetime类型) 请问怎么写四条sql语句分别按日,按周,按月,按季统计消费总量. 如:1月 120 ...

  5. Oracle笔记 八、PL/SQL跳转/判断/循环语句块

    --goto跳转语句 --在goto 后,跳转到相应的语句,然后执行该语句和后面所有语句 begin dbms_output.put_line('goto开始了'); goto c; --不被执行 d ...

  6. 一条SQL语句中算日销售额和月销售额

    刚刚做项目的时候用到的 用户表:用户ID,用户名,余额 流水表:时间,用户ID,用户名,类型(0充值,1消费),变更金额 现在要查每个用户的日销售额和月销售额,本来最简单的方法是先把所有用户查出来,然 ...

  7. SQL实现一年中每个日期剔除节假日和星期天之后的五个日期是多少

    最近公司OA系统的需求,实现一年中每个日期剔除节假日和星期天之后的五个日期是几号,每个日期都要跳过节假日和星期天,当时是真的慌了,郁闷了一天,后来半夜忽然来灵感,想想还是可以实现. 需要做一张节假日的 ...

  8. c# 计算两日期的工作时间间隔(排除非工作日)及计算下一个工作时间点.

    一个日期段如工作时间为 8:00 至 17:00 public class TimeHelper { /// <summary> /// 计算时间间隔 /// </summary&g ...

  9. SQL Server误区30日谈 第26天 SQL Server中存在真正的“事务嵌套”

    误区 #26: SQL Server中存在真正的“事务嵌套”错误 嵌套事务可不会像其语法表现的那样看起来允许事务嵌套.我真不知道为什么有人会这样写代码,我唯一能够想到的就是某个哥们对SQL Serve ...

随机推荐

  1. Eclipse反编译插件 Enhanced Class Decompiler

    因为jar包中的源码都是经过反编译的,所以需要安装插件才能查看到源码,此处介绍的是 Enhanced Class Decompiler 插件. 打开Eclipse,Help --> Eclips ...

  2. Java,泛型类型通配符和C#对照

    c#的泛型没有类型通配符,原因是.net的泛型是CLR支持的泛型,而Java的JVM并不支持泛型,仅仅是语法糖,在编译器编译的时候都转换成object类型 类型通配符在java中表示的是泛型类型的父类 ...

  3. 面试基础_03实现strcpy、strcat、strcmp、strlen

    实现代码例如以下: /************************************************************************* > File Name: ...

  4. sass02

    新建一个文件夹 1 cd 进入文件夹 ,cd E:\360data\重要数据\桌面\sass, 2 compass creat hello:当前目录创建sass工程, 3 sass文件夹放置sass文 ...

  5. apiCloud手动检测更新

    有时候需要给用户一个自主的权利,自主检测app是否是最新版本. 如何实现? 1.点击调用接口,检测是否有更新. 默认APICloud会自动检测版本更新,用户也可以在config.xml里配置autoU ...

  6. IOC DI 专题

    IoC:Inversion of Control,控制反转DI:Dependency Injection,依赖注入 要理解上面两个概念,就必须搞清楚如下的问题: 参与者都有谁?依赖:谁依赖于谁?为什么 ...

  7. 学习《零基础入门学习Python》电子书PDF+笔记+课后题及答案

    初学python入门建议学习<零基础入门学习Python>.适合新手入门,很简单很易懂.前一半将语法,后一半讲了实际的应用. Python3入门必备,小甲鱼手把手教授Python,包含电子 ...

  8. 安卓https

    http://www.tuicool.com/articles/NrmE3e http://blog.csdn.net/guestcode/article/details/50194357 http: ...

  9. Gonet2 游戏server框架解析之Agent(3)

    客户端消息在Agent中的预处理流程. Agent定义好的三种请求: //api.go var RCode = map[int16]string{ 0: "heart_beat_req&qu ...

  10. [Python] Find available methods and help in REPL

    For example you want to know what methods are available in Python for String, you can do : dir(" ...