2017-09-21 56 views
0

如何在此情況下排除週末並僅在給定日期之間獲得時間差異,以下是方案。排除週末並在SQL中獲取時間

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

select 
    Convert(varchar(5),datediff(s, @d1, @d2)/3600 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end) 
     +':'+ 
     convert(Varchar(5),datediff(s, @d1, @d2)%3600/60 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end) 
      +':'+ 
     convert(Varchar(5),datediff(s, @d1, @d2)%60 - (datediff(wk, @d1, @d2) * 2) - 
     case when datepart(dw, @d1) = 1 then 24 else 0 end + 
     case when datepart(dw, @d2) = 1 then 24 else 0 end 
     ) as hrs 
+0

「週末」,你真的是指「非工作日」嗎?因爲這些不是一回事。而且由於自然災害引發了新聞,所以即使是「標準」工作日也可能實際上並未「起作用」。你如何解決這個問題?在互聯網上搜索「日曆表」。 – SMor

回答

0

一個想法是找到的第一個星期一(如果我們說,「週末」是指週六和週日)或之後@ D1和上週一@ D2之前。這是整週的數量。所以整整一週的時間是120(5天* 24小時)。然後,我們將在上個星期一之後添加小時,直到@ d2。 @ d2星期幾的一個簡單例子可以讓你在上週的週末裏照顧週末。同樣,我們會計算@ d1到第一個星期一之間的小時數。

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

declare @StartOfFirstWeekAfterStartDate date = cast(dateadd(day, case datepart(weekday, @d1) 
    when 1 /* Sunday */ then -6 
    when 2 /* Monday */ then 0 
    when 3 /* Tuesday */ then 6 
    when 4 /* Wendsday */ then 5 
    when 5 /* Thursday */ then 4 
    when 6 /* Friday */ then 3 
    when 7 /* Saturday */ then 2 
    end, @d1) as date), 
    @StartOfLastWeekBeforeEndDate date = cast(dateadd(day, case datepart(weekday, @d2) 
    when 1 /* Sunday */ then -6 
    when 2 /* Monday */ then 0 
    when 3 /* Tuesday */ then -1 
    when 4 /* Wendsday */ then -2 
    when 5 /* Thursday */ then -3 
    when 6 /* Friday */ then -4 
    when 7 /* Saturday */ then -5 
    end, @d2) as date) 

declare @NumberOfWorkdays int = datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate) * 5 

declare @HoursWeekBefore int = case datepart(weekday, @d1) 
    when 1 /* Sunday */ then 0 
    when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1) 
    when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1) 
    when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1) 
    when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1) 
    when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1) 
    when 7 /* Saturday */ then 0 
    end 

declare @HoursWeekAfter int = case datepart(weekday, @d2) 
    when 1 /* Sunday */ then 5 * 24 
    when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2) 
    when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2) 
    when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2) 
    when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2) 
    when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2) 
    when 7 /* Saturday */ then 5 * 24 
    end 

declare @HoursDiff int = @HoursWeekBefore + @NumberOfWorkdays * 24 + @HoursWeekAfter 

select 
    @StartOfFirstWeekAfterStartDate, 
    datepart(WEEKDAY, @StartOfFirstWeekAfterStartDate), -- Should always be Monday 
    @StartOfLastWeekBeforeEndDate, 
    datepart(WEEKDAY, @StartOfLastWeekBeforeEndDate), -- Should always be Monday 
    @NumberOfWorkdays, 
    datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate), 
    @HoursWeekBefore, 
    @HoursWeekAfter, 
    @HoursDiff 

上面的代碼適用於sp/udf的使用。如果我們把所有這些計算在一個表達式,它會成爲這樣:

declare @d1 datetime, @d2 datetime 
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000' 

select case datepart(weekday, @d1) 
    when 1 /* Sunday */ then 0 
    when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1) 
    when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1) 
    when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1) 
    when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1) 
    when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1) 
    when 7 /* Saturday */ then 0 
    end /* @HoursWeekBefore */ 
    + 
    datediff(week, 
     cast(dateadd(day, case datepart(weekday, @d1) 
      when 1 /* Sunday */ then -6 
      when 2 /* Monday */ then 0 
      when 3 /* Tuesday */ then 6 
      when 4 /* Wendsday */ then 5 
      when 5 /* Thursday */ then 4 
      when 6 /* Friday */ then 3 
      when 7 /* Saturday */ then 2 
      end, @d1) as date) /* @StartOfFirstWeekAfterStartDate */, 
     cast(dateadd(day, case datepart(weekday, @d2) 
      when 1 /* Sunday */ then -6 
      when 2 /* Monday */ then 0 
      when 3 /* Tuesday */ then -1 
      when 4 /* Wendsday */ then -2 
      when 5 /* Thursday */ then -3 
      when 6 /* Friday */ then -4 
      when 7 /* Saturday */ then -5 
      end, @d2) as date) /* @StartOfLastWeekBeforeEndDate */) * 5 /* @NumberOfWorkdays */ * 24 
    + 
    case datepart(weekday, @d2) 
     when 1 /* Sunday */ then 5 * 24 
     when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2) 
     when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2) 
     when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2) 
     when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2) 
     when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2) 
     when 7 /* Saturday */ then 5 * 24 
     end /* @HoursWeekAfter */ 

請,不就是上面的計算取決於DATEFIRST設置。我假設星期日是一週的第一天(即datepart(weekday,@Moday)將返回2)。如果不是這種情況,則應調整案例陳述中的偏移量。 我也沒有在這些時間處理會議紀要,所以小時計算有點粗糙。如果這是一個問題,你可以使用上面的方法來計算@ D1和D2 @和60

+0

謝謝Andrey Nikolov在這方面幫助我,不過週六是一週中的第一天。是否可以相應修改並幫助我。我在這些編碼方面是新手,並且讓我感到困惑,因此請求修改代碼。 –

+0

您應該在此查詢的頂部添加** set DATEFIRST 7 **(將星期的第一天更改爲星期日)或更改case語句中的數字,其中** datepart(weekday)**爲星期日爲2,星期一爲3,星期二爲4,星期三爲5,星期四爲6,星期五爲6,星期五爲7,星期六爲1。 –

0
create function DateDiffWeekends(@a date, @b date) 
returns int as 
BEGIN 
DECLARE @Result int 
SELECT @Result = DateDiff(dd,@a,@b) 
       - DateDiff(ww,@a,@b)*2 
       - case DatePart(dw,@a) when 1 then 1 else 0 end 
       - case DatePart(dw,@b) when 7 then 1 else 0 end 
RETURN @Result 
End 

這是劃分這之間的分鐘數(類似),我是一個功能使用生產環境。我將分解SELECT @Result區域的四個公式中的每一個在做什麼。

DateDiff(dd,@a,@b) 

這只是找到兩個日期之間的天數。經典DateDiff。

- DateDiff(ww,@a,@b)*2 

這會找出兩天之間的星期數,並將其乘以2。這個原因是因爲它計算了週休息的次數,而不是「7天的細分」的數量。例如,如果我選擇星期五和下一個星期一的日期,DateDiff(ww,$Saturday,$Monday)將返回1周,即使它們在技術上相隔2天。

- case DatePart(dw,@a) when 1 then 1 else 0 end 

如果你選擇星期日的開始日期,那麼你將需要再花一天的時間結果。如果你的開始日期是星期六,那麼它將在不同的一週,所以前面的陳述將會照顧它。

- case DatePart(dw,@b) when 7 then 1 else 0 end 

如果您選擇星期六的結束日期,那麼您還需要休息一天。如果您的結束日期是星期日,那麼它將再次處於不同的一週。

這是SQLFiddle如果你想測試/玩它。

編輯:我只是注意到,你也問過時間。我會在這裏留下這個答案,以防其他人有用,但它可能不適用於你的情況。