SQL Server我对使用datepart进行工作日计算感到疯狂

时间:2019-02-14 16:49:42

标签: sql sql-server

我正在使用SQL-Server 2012,并具有以下代码示例来获取两个日期之间的工作日

DECLARE @StartDate AS date
DECLARE @EndDate AS date

SET @StartDate = '2019/02/18' -- this is a monday
SET @EndDate = '2019/02/23'  -- this is a saturday

SELECT 
       DATEDIFF(DD, @StartDate, @EndDate) 
       - (DATEDIFF(WK, @StartDate,@EndDate) * 2) 
       - CASE WHEN DATEPART(DW, @StartDate) = 1 THEN 1 ELSE 0 END 
       - CASE WHEN DATEPART(DW, @EndDate) = 1 THEN 1 ELSE 0 END

结果是4,这是正确的...

但是如果我将2019/02/24(星期日)作为EndDate,我将获得3 ... ????

我在这里疯了...

3 个答案:

答案 0 :(得分:2)

您正在确认结束日期为星期日而不是星期六。我有类似的可用功能,与日期设置无关。

SELECT ISNULL((((DATEDIFF(dd,@StartDate,@EndDate)) --Start with total number of days including weekends
              - (DATEDIFF(wk,@StartDate,@EndDate)*2) --Subtact 2 days for each full weekend
              - (1-SIGN(DATEDIFF(dd,6,@StartDate)%7)) --If StartDate is a Sunday, Subtract 1
              - (1-SIGN(DATEDIFF(dd,5,@EndDate)  %7)))) , 0)  --If StartDate is a Saturday, Subtract 1
    WHERE @StartDate <= @EndDate

答案 1 :(得分:1)

@Luis Cazares的答案非常有用,除了当开始日期或结束日期是星期六或星期日时,该数字为1。另外,不考虑假期(如果在讨论之内)。

这是构造函数的方式。

    CREATE FUNCTION [dbo].[getWorkDays] (@startDate date, @endDate date)  
    RETURNS int

    AS  
    BEGIN  

        DECLARE @daysct int = 0;
        DECLARE @currentDate date = @startDate;

        IF @endDate>@startDate
            GOTO COUNTIT;
        ELSE
            GOTO ZERO;


    COUNTIT:
    BEGIN
    --Pre-process: if the startDate is holiday or weekend, then step in until the next business day
        WHILE datepart(weekday, @currentDate) in (1, 7) OR EXISTS (SELECT holiday_date FROM dbo.holidays WHERE holiday_date = @currentDate)   --if weekend or holiday
        BEGIN
            SET @currentDate = dateadd(day, 1, @currentDate);
            SET @daysct=1;
        END    

        WHILE @currentDate <= @endDate
        BEGIN
        IF @currentDate=@endDate
            BREAK;
        ELSE 
            IF datepart(weekday, @currentDate) not in (1, 7) AND NOT EXISTS (SELECT holiday_date FROM dbo.holidays WHERE holiday_date = @currentDate)   --if not weekend and not holiday
            BEGIN
                SET @daysct=@daysct + 1;
            END
        SET @currentDate=dateadd(day, 1, @currentDate);
        END

    --Post-process: if the end date DOES NOT fall on a weekend or holiday, then @daysct is systematically 1 below. Add 1 to straighten it.
        IF datepart(weekday, @endDate) in (1, 7) OR EXISTS (SELECT holiday_date FROM dbo.holidays WHERE holiday_date = @endDate)
            SET @daysct = @daysct - 1;

        RETURN(@daysct);
    END

    ZERO:
    BEGIN
        SET @daysct=0;    
        RETURN(@daysct);  
    END
    END;

这不是最有效的代码,但自然是我手工计算的过程。要注意的是,您需要声明一个变量或常量,否则会大大降低查询速度。

DECLARE @days_worked int = dbo.getWorkDays(dateadd(day,1,eomonth(getdate()AT TIME ZONE'Pacific Standard Time',-1)),getdate()AT TIME ZONE'Pacific Standard Time');

此外,在使用它之前,请确保您有一个假期表。我的桌子是用这种方式构造的。

enter image description here

答案 2 :(得分:0)

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://127.0.0.1:5556")
topic = "img_rgba"
time.sleep(2)
while(1):
    [...]   
    socket.send_string(topic, zmq.SNDMORE)
    socket.send_pyobj(image)