从星期开始的天数(不包括周末)

问题描述 投票:0回答:1

这是查询的一部分,该查询根据时间范围“本周”以及合同的开始和结束日期(按小时计费)来计算合同的总收入。

SELECT (ChargeRate - PayRate) * 8 * 
    CASE 
        WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP) 
        AND ContractEndDate >= CURRENT_TIMESTAMP
            THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
        WHEN ContractEndDate <= CURRENT_TIMESTAMP 
        AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
        AND ContractStartDate <= CURRENT_TIMESTAMP
            THEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, ContractEndDate), ContractEndDate), ContractEndDate)
        WHEN ContractStartDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
        AND ContractStartDate <= CURRENT_TIMESTAMP
        AND ContractStartDate >= CURRENT_TIMESTAMP
            THEN DATEDIFF(DAY, ContractStartDate, CURRENT_TIMESTAMP)
        WHEN ContractEndDate <= CURRENT_TIMESTAMP 
        AND ContractEndDate >= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
        AND ContractStartDate >= CURRENT_TIMESTAMP
            THEN  DATEDIFF(DAY, ContractStartDate, ContractEndDate)
        ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
    END

我正在苦苦挣扎的是如何排除周六和周日,因此计数永远不会超过5,而周日不是一周的开始,而是星期一。因此,根据查询运行的日期,工作天数最终将为[ Monday = 1, Tuesday = 2 ... Friday = 5, Saturday = 5, Sunday = 5 ]

目前发生的情况是,如果这些图形在周六运行,则计算使用6天,如果在周日运行,则计算使用0天。一周中的每一天都是正确的,这可以通过以下查询看到:

DECLARE @StartDate DATETIME = '2019-12-1'
DECLARE @StartDate2 DATETIME = '2019-11-30'

SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, @StartDate), @StartDate), @StartDate)
SELECT DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, @StartDate2), @StartDate2), @StartDate2)

结果应为0和6。

我唯一能想到的解决方案是嵌套case语句,并检查值是否为0或6,然后将其更改为5,如下所示:

WHEN ContractStartDate <= DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP) 
AND ContractEndDate >= CURRENT_TIMESTAMP
    THEN 
        CASE 
            WHEN DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP) IN (0,6)
                THEN 5
            ELSE DATEDIFF(DAY, DATEADD(DAY, 1-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP), CURRENT_TIMESTAMP)
        END

这是可行的,但是有点混乱,我很想看看是否有更好的解决方案。

sql tsql
1个回答
1
投票

这是一种方法,它是通过SQLServerCentral从Jeff Moden借来的。 (我会对此回复发表评论,但我的观点不充分:()

--count weekdays between two dates
DECLARE @StartDate DATETIME = '2019-11-01'
DECLARE @EndDate DATETIME = '2019-11-30'

SELECT (DATEDIFF(DD, @StartDate, @EndDate) + 1) --Total days in period, including weekends
  -(DATEDIFF(WK, @StartDate, @EndDate) * 2) --minus number of whole weekends in the period * 2 days
  -(CASE WHEN DATENAME(DW, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) --minus 1 if the period starts on a Sunday
  -(CASE WHEN DATENAME(DW, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) --minus 1 if the period ends on a Saturday

当然,这里有一些问题,例如英文日期名称的使用不太方便,但可以在需要时解决。

我在“ WeekdayCount”功能中内置了此功能,非常方便!

更多详细信息:https://www.sqlservercentral.com/articles/calculating-work-days

© www.soinside.com 2019 - 2024. All rights reserved.