2013-06-18 21 views
0

我有这似乎很好地工作,但它总是比数,我需要1少的情况如下:DATEDIFF始终是1号少于我需要

DECLARE @start_day DATETIME; 
DECLARE @end_day DATETIME; 
DECLARE @start_time DATETIME; 
DECLARE @end_time DATETIME; 

SET @start_day = '2013-06-03'; 
SET @end_day = '2013-06-07'; 

PRINT DATEDIFF(d, @start_day, @end_day) 
     - DATEDIFF(wk, @start_day, @end_day) * 2 
     - CASE 
      WHEN DATEPART(dw, @start_day) != 7 AND DATEPART(dw, @end_day) = 7 THEN 1 
      WHEN DATEPART(dw, @start_day) = 7 AND DATEPART(dw, @end_day) != 7 THEN -1 
      ELSE 0 
     END 

我应该得到

`5` for `2013-06-03` to `2013-06-07` but it's giving me `4`. 
`5` for `2013-06-03` to `2013-06-08` but it's giving me `4`. 
`5` for `2013-06-03` to `2013-06-09` but it's giving me `4`. 
`6` for `2013-06-03` to `2013-06-10` but it's giving me `5`. 

所以我的问题是:

如何获得:

`2013-06-03` to `2013-06-07` to equal 5 
`2013-06-03` to `2013-06-08` to equal 5 
`2013-06-03` to `2013-06-09` to equal 5 
`2013-06-03` to `2013-06-10` to equal 6 

请注意,在末尾添加+1并不能解决问题!

+0

这是行不通的。如果我这样做,它也会在周末加1,这是不应该做的。 – oshirowanen

+1

'DATEDIFF'就是这样工作的。 “2013-6-18”和“2013-6-18”之间的区别肯定应该是“0”。所以'2013-6-18'和'2013-6-19'之间的区别将会是'1' ...等etc –

+0

我的第二个评论不是针对您的第一条评论... –

回答

1
Create table foo (
StartDate datetime not null, 
EndDate datetime not null 
) 

insert into foo (StartDate, EndDate) values (N'2013-06-03', N'2013-06-07'), 
(N'2013-06-03', N'2013-06-08'), 
(N'2013-06-03', N'2013-06-09'), 
(N'2013-06-03', N'2013-06-10') 

SELECT 
    DATEDIFF(d, StartDate, EndDate) 
    + CASE 
     WHEN DATEPART(dw, StartDate) <= 5 THEN 1 
     ELSE 0 
     END 
    - DATEDIFF(wk, StartDate, EndDate) * 2 
    - CASE 
     WHEN DATEPART(dw, StartDate) != 7 AND DATEPART(dw, EndDate) = 7 THEN 1 
     WHEN DATEPART(dw, StartDate) = 7 AND DATEPART(dw, EndDate) != 7 THEN -1 
     ELSE 0 
    END 
FROM foo 

SqlFiddle

+0

如果'start = 2013-06-01'和'end = 2013-06-03',这给了我一个'2'。它应该给我'1'。 – oshirowanen

+0

'start = 2013-06-01'和'end = 2013-06-01' –

+0

'start = 2013-06-01'和'end = 2013-06-01'应该是'0' '因为它不是星期一,星期二,星期三,星期四或星期五。 – oshirowanen

0

如果你是想复制Excel的NETWORKDAYS然后我这个年龄前写...

CREATE FUNCTION [dbo].[fnNetworkDays] 
(
    @date1 SMALLDATETIME, 
    @date2 SMALLDATETIME 
) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @ret INT, 
      @dt1 INT, 
      @dt2 INT, 
      @dt3 INT, 
      @neg INT, 
      @wks INT, 
      @dyo INT, 
      @wkd INT, 
      @take INT 
    --Midnightise the dates 
    SELECT @date1 = DATEADD(dd,0, DATEDIFF(dd,0,@date1)), @date2 = DATEADD(dd,0, DATEDIFF(dd,0,@date2)) 
    --Get integers to make the calcs easier 
    SELECT @dt1 = CONVERT(INT,@date1),@dt2 = CONVERT(INT,@date2) 

    IF @dt1 > @dt2 
     BEGIN 
     SET @neg = -1 
     SET @dt3 = @dt1 
     SET @dt1 = @dt2 
     SET @dt2 = @dt3 
     END 
    ELSE 
     SET @neg = 1 

    SET @ret = @dt2 - @dt1 + 1 
    SET @wks = FLOOR(@ret/7) 
    SET @dyo = @ret % 7 
    SET @wkd = @dt1 % 7 

    SELECT @take=CASE @wkd 
     WHEN 0 THEN CASE WHEN @dyo = 6 THEN 1 ELSE 0 END 
     WHEN 6 THEN CASE WHEN @dyo = 1 THEN 1 ELSE 0 END 
     ELSE CASE WHEN @dyo = (6 - @wkd) THEN 1 ELSE CASE WHEN @dyo > (6 - @wkd) THEN 2 ELSE 0 END END 
    END 

    SELECT @ret = @neg * (@ret - @wks * 2 - @take) 

    RETURN @ret 
END 

可能过于复杂,但它的工作原理。

0

我宁愿使用一个计数和理货表。

SELECT COUNT(*) 
FROM dbo.tTally 
WHERE n BETWEEN DATEDIFF(dd, 0, @from) AND DATEDIFF(dd, 0, @to) 
AND DATEPART(dw, DATEADD(dd, n, 0)) NOT IN (7, 1) 

tally table