2008-10-31 126 views
123

如何計算SQL Server中兩個日期之間的工作天數?計算兩個日期之間的工作日

週一至週五,它必須是T-SQL。

+5

你能定義工作日嗎?星期五到星期五?不包括主要假期?什麼國家?必須在SQL中完成嗎? – 2008-10-31 03:29:35

回答

238

對於工作日,週一到週五,你可以用一個SELECT做到這一點,就像這樣:

DECLARE @StartDate DATETIME 
DECLARE @EndDate DATETIME 
SET @StartDate = '2008/10/01' 
SET @EndDate = '2008/10/31' 


SELECT 
    (DATEDIFF(dd, @StartDate, @EndDate) + 1) 
    -(DATEDIFF(wk, @StartDate, @EndDate) * 2) 
    -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) 
    -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) 

如果要包括節假日,你必須解決它有點...

+3

不錯的答案+1 :) – 2010-04-18 13:11:01

+1

我剛剛意識到這個代碼並不總是工作!我試過這個:SET @StartDate = '28 -mar-2011' SET @EndDate = '29 -mar-2011' 它的計算結果爲2天 – greektreat 2011-03-30 14:33:47

+12

@greektreat它工作正常。這只是@StartDate和@EndDate都包含在計數中。如果您希望星期一到星期二計算爲1天,只需在第一個DATEDIFF後刪除「+ 1」即可。那麼你也會得到Fri-> Sat = 0,Fri-> Sun = 0,Fri-> Mon = 1。 – 2011-04-04 01:11:43

27

Calculating Work Days你可以找到關於這個問題的好文章,但正如你可以看到它不是先進的。

--Changing current database to the Master database allows function to be shared by everyone. 
USE MASTER 
GO 
--If the function already exists, drop it. 
IF EXISTS 
(
    SELECT * 
    FROM dbo.SYSOBJECTS 
    WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]') 
    AND XType IN (N'FN', N'IF', N'TF') 
) 
DROP FUNCTION [dbo].[fn_WorkDays] 
GO 
CREATE FUNCTION dbo.fn_WorkDays 
--Presets 
--Define the input parameters (OK if reversed by mistake). 
(
    @StartDate DATETIME, 
    @EndDate DATETIME = NULL [email protected] replaced by @StartDate when DEFAULTed 
) 

--Define the output data type. 
RETURNS INT 

AS 
--Calculate the RETURN of the function. 
BEGIN 
    --Declare local variables 
    --Temporarily holds @EndDate during date reversal. 
    DECLARE @Swap DATETIME 

    --If the Start Date is null, return a NULL and exit. 
    IF @StartDate IS NULL 
     RETURN NULL 

    --If the End Date is null, populate with Start Date value so will have two dates (required by DATEDIFF below). 
    IF @EndDate IS NULL 
     SELECT @EndDate = @StartDate 

    --Strip the time element from both dates (just to be safe) by converting to whole days and back to a date. 
    --Usually faster than CONVERT. 
    --0 is a date (01/01/1900 00:00:00.000) 
    SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate), 0), 
      @EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) , 0) 

    --If the inputs are in the wrong order, reverse them. 
    IF @StartDate > @EndDate 
     SELECT @Swap  = @EndDate, 
       @EndDate = @StartDate, 
       @StartDate = @Swap 

    --Calculate and return the number of workdays using the input parameters. 
    --This is the meat of the function. 
    --This is really just one formula with a couple of parts that are listed on separate lines for documentation purposes. 
    RETURN (
     SELECT 
     --Start with total number of days including weekends 
     (DATEDIFF(dd,@StartDate, @EndDate)+1) 
     --Subtact 2 days for each full weekend 
     -(DATEDIFF(wk,@StartDate, @EndDate)*2) 
     --If StartDate is a Sunday, Subtract 1 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' 
      THEN 1 
      ELSE 0 
     END) 
     --If EndDate is a Saturday, Subtract 1 
     -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' 
      THEN 1 
      ELSE 0 
     END) 
     ) 
    END 
GO 

如果您需要使用自定義日曆,則可能需要添加一些檢查和一些參數。希望它能提供一個很好的起點。

+0

感謝您提供鏈接以瞭解其工作原理。寫在sqlservercentral是偉大的! – 2013-02-26 22:36:56

+0

感謝您的內嵌評論。他們幫助我很快看到這是如何工作的。 – unnknown 2014-04-09 17:31:49

4
DECLARE @TotalDays INT,@WorkDays INT 
DECLARE @ReducedDayswithEndDate INT 
DECLARE @WeekPart INT 
DECLARE @DatePart INT 

SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1 
SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate) 
    WHEN 'Saturday' THEN 1 
    WHEN 'Sunday' THEN 2 
    ELSE 0 END 
SET @[email protected]@ReducedDayswithEndDate 
SET @[email protected]/7; 
SET @[email protected]%7; 
SET @WorkDays=(@WeekPart*5)[email protected] 

RETURN @WorkDays 
1
DECLARE @StartDate datetime,@EndDate datetime 

select @StartDate='3/2/2010', @EndDate='3/7/2010' 

DECLARE @TotalDays INT,@WorkDays INT 

DECLARE @ReducedDayswithEndDate INT 

DECLARE @WeekPart INT 

DECLARE @DatePart INT 

SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1 

SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate) 
    WHEN 'Saturday' THEN 1 
    WHEN 'Sunday' THEN 2 
    ELSE 0 END 

SET @[email protected]@ReducedDayswithEndDate 

SET @[email protected]/7; 

SET @[email protected]%7; 

SET @WorkDays=(@WeekPart*5)[email protected] 

SELECT @WorkDays 
6

我使用DATEPART接受的答案作爲函數的版本,所以我沒有做就行了字符串比較

DATENAME(dw, @StartDate) = 'Sunday' 

不管怎麼說,這是我的事DATEDIFF函數

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

CREATE FUNCTION BDATEDIFF 
(
    @startdate as DATETIME, 
    @enddate as DATETIME 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @res int 

SET @res = (DATEDIFF(dd, @startdate, @enddate) + 1) 
    -(DATEDIFF(wk, @startdate, @enddate) * 2) 
    -(CASE WHEN DATEPART(dw, @startdate) = 1 THEN 1 ELSE 0 END) 
    -(CASE WHEN DATEPART(dw, @enddate) = 7 THEN 1 ELSE 0 END) 

    RETURN @res 
END 
GO 
1
CREATE FUNCTION x 
(
    @StartDate DATETIME, 
    @EndDate DATETIME 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @Teller INT 

    SET @StartDate = DATEADD(dd,1,@StartDate) 

    SET @Teller = 0 
    IF DATEDIFF(dd,@StartDate,@EndDate) <= 0 
    BEGIN 
     SET @Teller = 0 
    END 
    ELSE 
    BEGIN 
     WHILE 
      DATEDIFF(dd,@StartDate,@EndDate) >= 0 
     BEGIN 
      IF DATEPART(dw,@StartDate) < 6 
      BEGIN 
       SET @Teller = @Teller + 1 
      END 
      SET @StartDate = DATEADD(dd,1,@StartDate) 
     END 
    END 
    RETURN @Teller 
END 
5

(我有幾點害羞的評論權限)

如果你決定放棄+1天CMS's elegant solution,請注意,如果您的開始日期和結束日期在同一個週末,您會得到一個否定答案。即,2008/10/26至2008/10/26返回-1。

我而簡單的解決方案:

select @Result = (..CMS's answer..) 
if (@Result < 0) 
     select @Result = 0 
    RETURN @Result 

... 結束日期到零之後,也將所有錯誤的帖子與開始日期。你可能會或可能不會在尋找的東西。

5

對於日期,包括節假日之間的差異我就這樣說:

1)表與假日:

CREATE TABLE [dbo].[Holiday](
[Id] [int] IDENTITY(1,1) NOT NULL, 
[Name] [nvarchar](50) NULL, 
[Date] [datetime] NOT NULL) 

2)我有我的尼洋河表像這樣,想填列Work_Days裏面空無一人:

CREATE TABLE [dbo].[Plan_Phase](
[Id] [int] IDENTITY(1,1) NOT NULL, 
[Id_Plan] [int] NOT NULL, 
[Id_Phase] [int] NOT NULL, 
[Start_Date] [datetime] NULL, 
[End_Date] [datetime] NULL, 
[Work_Days] [int] NULL) 

3)因此,爲了得到 「Work_Days」 後來在我的專欄填寫剛剛到:

SELECT Start_Date, End_Date, 
(DATEDIFF(dd, Start_Date, End_Date) + 1) 
-(DATEDIFF(wk, Start_Date, End_Date) * 2) 
-(SELECT COUNT(*) From Holiday Where Date >= Start_Date AND Date <= End_Date) 
-(CASE WHEN DATENAME(dw, Start_Date) = 'Sunday' THEN 1 ELSE 0 END) 
-(CASE WHEN DATENAME(dw, End_Date) = 'Saturday' THEN 1 ELSE 0 END) 
-(CASE WHEN (SELECT COUNT(*) From Holiday Where Start_Date = Date) > 0 THEN 1 ELSE 0 END) 
-(CASE WHEN (SELECT COUNT(*) From Holiday Where End_Date = Date) > 0 THEN 1 ELSE 0 END) AS Work_Days 
from Plan_Phase 

希望我能幫上忙。

乾杯

1

我把各種例子在這裏,但在我的特殊情況,我們有用於輸送@PromisedDate和實際收到該項目的@ReceivedDate。當在「PromisedDate」之前收到一個項目時,除非我按日曆順序將日期傳遞到函數中,否則計算的總計不正確。不想每次都檢查日期,我改變了功能來處理這個問題。

Create FUNCTION [dbo].[fnGetBusinessDays] 
(
@PromiseDate date, 
@ReceivedDate date 
) 
RETURNS integer 
AS 
BEGIN 
DECLARE @days integer 

SELECT @days = 
    Case when @PromiseDate > @ReceivedDate Then 
     DATEDIFF(d,@PromiseDate,@ReceivedDate) + 
     ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 + 
     CASE 
      WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1 
      WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1 
      ELSE 0 
     END + 
     (Select COUNT(*) FROM CompanyHolidays 
      WHERE HolidayDate BETWEEN @ReceivedDate AND @PromiseDate 
      AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday') 
    Else 
     DATEDIFF(d,@PromiseDate,@ReceivedDate) - 
     ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 - 
      CASE 
       WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1 
       WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1 
       ELSE 0 
      END - 
     (Select COUNT(*) FROM CompanyHolidays 
      WHERE HolidayDate BETWEEN @PromiseDate and @ReceivedDate 
      AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday') 
    End 


RETURN (@days) 

END 
4

這是一個很好的(我認爲)的版本。假期表包含Holiday_date列,其中包含貴公司觀察的假期。

DECLARE @RAWDAYS INT 

    SELECT @RAWDAYS = DATEDIFF(day, @StartDate, @EndDate)--+1 
        -(2 * DATEDIFF(week, @StartDate, @EndDate)) 
        + CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END 
        - CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END 

    SELECT @RAWDAYS - COUNT(*) 
    FROM HOLIDAY NumberOfBusinessDays 
    WHERE [Holiday_Date] BETWEEN @StartDate+1 AND @EndDate 
14

All Credit to Bogdan Maxim & Peter Mortensen。這是他們的崗位,我只是說假期的函數(這裏假設你有一個表「tblHolidays」與時間字段「HolDate」。

--Changing current database to the Master database allows function to be shared by everyone. 
USE MASTER 
GO 
--If the function already exists, drop it. 
IF EXISTS 
(
    SELECT * 
    FROM dbo.SYSOBJECTS 
    WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]') 
    AND XType IN (N'FN', N'IF', N'TF') 
) 

DROP FUNCTION [dbo].[fn_WorkDays] 
GO 
CREATE FUNCTION dbo.fn_WorkDays 
--Presets 
--Define the input parameters (OK if reversed by mistake). 
(
    @StartDate DATETIME, 
    @EndDate DATETIME = NULL [email protected] replaced by @StartDate when DEFAULTed 
) 

--Define the output data type. 
RETURNS INT 

AS 
--Calculate the RETURN of the function. 
BEGIN 
    --Declare local variables 
    --Temporarily holds @EndDate during date reversal. 
    DECLARE @Swap DATETIME 

    --If the Start Date is null, return a NULL and exit. 
    IF @StartDate IS NULL 
     RETURN NULL 

    --If the End Date is null, populate with Start Date value so will have two dates (required by DATEDIFF below). 
    IF @EndDate IS NULL 
     SELECT @EndDate = @StartDate 

    --Strip the time element from both dates (just to be safe) by converting to whole days and back to a date. 
    --Usually faster than CONVERT. 
    --0 is a date (01/01/1900 00:00:00.000) 
    SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate), 0), 
      @EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) , 0) 

    --If the inputs are in the wrong order, reverse them. 
    IF @StartDate > @EndDate 
     SELECT @Swap  = @EndDate, 
       @EndDate = @StartDate, 
       @StartDate = @Swap 

    --Calculate and return the number of workdays using the input parameters. 
    --This is the meat of the function. 
    --This is really just one formula with a couple of parts that are listed on separate lines for documentation purposes. 
    RETURN (
     SELECT 
     --Start with total number of days including weekends 
     (DATEDIFF(dd,@StartDate, @EndDate)+1) 
     --Subtact 2 days for each full weekend 
     -(DATEDIFF(wk,@StartDate, @EndDate)*2) 
     --If StartDate is a Sunday, Subtract 1 
     -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' 
      THEN 1 
      ELSE 0 
     END) 
     --If EndDate is a Saturday, Subtract 1 
     -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' 
      THEN 1 
      ELSE 0 
     END) 
     --Subtract all holidays 
     -(Select Count(*) from [DB04\DB04].[Gateway].[dbo].[tblHolidays] 
      where [HolDate] between @StartDate and @EndDate) 
     ) 
    END 
GO 
-- Test Script 
/* 
declare @EndDate datetime= dateadd(m,2,getdate()) 
print @EndDate 
select [Master].[dbo].[fn_WorkDays] (getdate(), @EndDate) 
*/ 
1

如果你需要工作日內添加到一個給定的日期,你可以創建依賴於日曆表的功能,如下所述:

CREATE TABLE Calendar 
(
    dt SMALLDATETIME PRIMARY KEY, 
    IsWorkDay BIT 
); 

--fill the rows with normal days, weekends and holidays. 


create function AddWorkingDays (@initialDate smalldatetime, @numberOfDays int) 
    returns smalldatetime as 

    begin 
     declare @result smalldatetime 
     set @result = 
     (
      select t.dt from 
      (
       select dt, ROW_NUMBER() over (order by dt) as daysAhead from calendar 
       where dt > @initialDate 
       and IsWorkDay = 1 
       ) t 
      where t.daysAhead = @numberOfDays 
     ) 

     return @result 
    end 
2

使用日期表:

DECLARE 
     @StartDate date = '2014-01-01', 
     @EndDate date = '2014-01-31'; 
    SELECT 
     COUNT(*) As NumberOfWeekDays 
    FROM dbo.Calendar 
    WHERE CalendarDate BETWEEN @StartDate AND @EndDate 
     AND IsWorkDay = 1; 

如果你沒有,你可以使用一個數字表:

DECLARE 
    @StartDate datetime = '2014-01-01', 
    @EndDate datetime = '2014-01-31'; 
    SELECT 
    SUM(CASE WHEN DATEPART(dw, DATEADD(dd, Number-1, @StartDate)) BETWEEN 2 AND 6 THEN 1 ELSE 0 END) As NumberOfWeekDays 
    FROM dbo.Numbers 
    WHERE Number <= DATEDIFF(dd, @StartDate, @EndDate) + 1 -- Number table starts at 1, we want a 0 base 

它們都應該是快速的,它消除了模糊性/複雜性。第一種選擇是最好的,但如果你沒有日曆表,你可以用CTE創建一個數字表。

0

這對我而言,在我的國家週六和週日是非工作日。

對我來說@StartDate和@EndDate的時間很重要。

CREATE FUNCTION [dbo].[fnGetCountWorkingBusinessDays] 
(
    @StartDate as DATETIME, 
    @EndDate as DATETIME 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @res int 

SET @StartDate = CASE 
    WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN DATEADD(dd, 2, DATEDIFF(dd, 0, @StartDate)) 
    WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN DATEADD(dd, 1, DATEDIFF(dd, 0, @StartDate)) 
    ELSE @StartDate END 

SET @EndDate = CASE 
    WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN DATEADD(dd, 0, DATEDIFF(dd, 0, @EndDate)) 
    WHEN DATENAME(dw, @EndDate) = 'Sunday' THEN DATEADD(dd, -1, DATEDIFF(dd, 0, @EndDate)) 
    ELSE @EndDate END 


SET @res = 
    (DATEDIFF(hour, @StartDate, @EndDate)/24) 
    - (DATEDIFF(wk, @StartDate, @EndDate) * 2) 

SET @res = CASE WHEN @res < 0 THEN 0 ELSE @res END 

    RETURN @res 
END 

GO 
0

創建功能,如:

CREATE FUNCTION dbo.fn_WorkDays(@StartDate DATETIME, @EndDate DATETIME= NULL) 
RETURNS INT 
AS 
BEGIN 
     DECLARE @Days int 
     SET @Days = 0 

     IF @EndDate = NULL 
       SET @EndDate = EOMONTH(@StartDate) --last date of the month 

     WHILE DATEDIFF(dd,@StartDate,@EndDate) >= 0 
     BEGIN 
       IF DATENAME(dw, @StartDate) <> 'Saturday' 
        and DATENAME(dw, @StartDate) <> 'Sunday' 
        and Not ((Day(@StartDate) = 1 And Month(@StartDate) = 1)) --New Year's Day. 
        and Not ((Day(@StartDate) = 4 And Month(@StartDate) = 7)) --Independence Day. 
       BEGIN 
        SET @Days = @Days + 1 
       END 

       SET @StartDate = DATEADD(dd,1,@StartDate) 
     END 

     RETURN @Days 
END 

你可以調用的函數,如:

select dbo.fn_WorkDays('1/1/2016', '9/25/2016') 

或者像:

select dbo.fn_WorkDays(StartDate, EndDate) 
from table1 
1

這基本上是CMS的答案,而不依賴在特定的語言環境中。而且由於我們是爲通用拍攝的,這意味着它應該適用於所有@@datefirst設置。

datediff(day, <start>, <end>) - datediff(week, <start>, <end>) * 2 
    /* if start is a Sunday, adjust by -1 */ 
    + case when datepart(weekday, <start>) = 8 - @@datefirst then -1 else 0 end 
    /* if end is a Saturday, adjust by -1 */ 
    + case when datepart(weekday, <end>) = (13 - @@datefirst) % 7 + 1 then -1 else 0 end 

datediff(week, ...)始終使用週週六到週日的邊界,使表達是確定的,並不需要進行修改(只要我們平日裏的定義是一致的週一至週五)日編號根據@@datefirst設置的不同而有所不同,修改後的計算通過一些模塊化算法的小複雜性來處理這種修正。

處理星期六/星期日事情的更清晰的方法是在提取星期值之前翻譯日期。在移動之後,數值將回到固定的(可能更爲熟悉的)編號,該編號從星期日的1開始,到星期六的7結束。

datediff(day, <start>, <end>) - datediff(week, <start>, <end>) * 2 
    + case when datepart(weekday, dateadd(day, @@datefirst, <start>)) = 1 then -1 else 0 end, 
    + case when datepart(weekday, dateadd(day, @@datefirst, <end>)) = 7 then -1 else 0 end 

我已經跟蹤了這種形式的解決方案,至少回到2002年的Itzik Ben-Gan文章。 (https://technet.microsoft.com/en-us/library/aa175781(v=sql.80).aspx)雖然它需要一個小的調整,因爲更新的date類型不允許日期算術,否則它是相同的。

0
Create Function dbo.DateDiff_WeekDays 
(
@StartDate DateTime, 
@EndDate DateTime 
) 
Returns Int 
As 

Begin 

Declare @Result Int = 0 

While @StartDate <= @EndDate 
Begin 
    If DateName(DW, @StartDate) not in ('Saturday','Sunday') 
     Begin 
      Set @Result = @Result +1 
     End 
     Set @StartDate = DateAdd(Day, +1, @StartDate) 
End 

Return @Result 

5

來計算工作日另一種方法是使用循環基本上遍歷的日期範圍,每當天被發現是內週一1加一 - 週五。計算使用while循環工作日完整的腳本如下所示:

CREATE FUNCTION [dbo].[fn_GetTotalWorkingDaysUsingLoop] 
(@DateFrom DATE, 
@DateTo   DATE 
) 
RETURNS INT 
AS 
     BEGIN 
         DECLARE @TotWorkingDays INT= 0; 
         WHILE @DateFrom <= @DateTo 
             BEGIN 
                 IF DATENAME(WEEKDAY, @DateFrom) IN('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday') 
                     BEGIN 
                         SET @TotWorkingDays = @TotWorkingDays + 1; 
                 END; 
                 SET @DateFrom = DATEADD(DAY, 1, @DateFrom); 
             END; 
         RETURN @TotWorkingDays; 
     END; 
GO 

儘管WHILE循環的選擇是更清潔,並使用較少的代碼行,所以它具有在環境中的性能瓶頸,特別是當潛力你的日期範圍跨越幾年。

你可以看到如何計算本文工作天數和小時以上的方法: https://www.sqlshack.com/how-to-calculate-work-days-and-hours-in-sql-server/

0

我發現下面的TSQL一個相當優雅的解決方案(我沒有權限運行功能)。我發現DATEDIFF忽略了DATEFIRST,我希望本週的第一天是星期一。我還希望將第一個工作日設置爲零,如果在週末的週末下降,則爲零。這可能會幫助誰的人有一個稍微不同的要求:)

它不處理銀行假日

SET DATEFIRST 1 
SELECT 
,(DATEDIFF(DD, [StartDate], [EndDate]))   
-(DATEDIFF(wk, [StartDate], [EndDate]))   
-(DATEDIFF(wk, DATEADD(dd,[email protected]@DATEFIRST,[StartDate]), DATEADD(dd,[email protected]@DATEFIRST,[EndDate]))) AS [WorkingDays] 
FROM /*Your Table*/ 
0

一種方法是「走的日期」從開始結合,即可完成的情況下表達它檢查如果一天不是星期六或星期天,並且標記它(週一爲1,週末爲0)。最後只需求和標誌(它等於1個標誌的計數,因爲另一個標誌爲0)給你的工作日數。

您可以使用GetNums(startNumber,endNumber)類型的效用函數,它會爲開始日期到結束日期的'循環'生成一系列數字。有關實現,請參閱http://tsql.solidq.com/SourceCodes/GetNums.txt。邏輯也可以擴展到迎合假期(假如你有假期表)

declare @date1 as datetime = '19900101' 
declare @date2 as datetime = '19900120' 

select sum(case when DATENAME(DW,currentDate) not in ('Saturday', 'Sunday') then 1 else 0 end) as noOfWorkDays 
from dbo.GetNums(0,DATEDIFF(day,@date1, @date2)-1) as Num 
cross apply (select DATEADD(day,n,@date1)) as Dates(currentDate) 
相關問題