2010-02-13 65 views
1

我意識到不同的解決方案會有「工作日」的不同變化,但在我的情況下,我的意思是星期一至星期五(含)。計算兩個日期之間有多少個工作天 - T-SQL?

基本上我已經創建了一個函數來爲我和我目前的解決方案進行計算。我擔心(以及提出這個問題的理由)是,我擔心這是實現這個目標的一個不好的方法,因爲函數被調用的頻率非常高。在過去的3個月中,在生產系統上被稱爲1200萬次,平均工人時間爲44毫秒。

這讓我想知道這是否是實現解決方案的正確方法。

首先這裏是我創建的功能:

CREATE FUNCTION [dbo].[fn_WorkDays] 
    (
    @StartDate DATETIME, 
    @EndDate DATETIME = NULL [email protected] replaced by @StartDate when DEFAULTed 
    ) 
    RETURNS INT 
AS 

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 

由於其使用的一個簡單的例子,我將運行這種類型的查詢:

SELECT MYTABLE.EntryDate 
    ,dbo.fn_WorkDays(MYTABLE.EntryDate, getutcdate()) as WorkingDays 
    FROM MYTABLE          

MyTable的可能含有5000個都具有不同的日期行在EntryDate列(5000調用函數)

我的問題是我在這裏錯過了一些東西,我這樣做,是否有利於創建一個廁所KUP表此(不過這是一個很大的日期組合)

任何想法,改進或建議,將不勝感激......

+0

看看這個答案和比較說明:http://stackoverflow.com/questions/1828948/mysql-function-to-find-the-number-of-working-days-between-two-dates/1828991 #1828991 – 2010-02-13 19:48:48

+0

是否可以添加一個額外字段(計算字段)並僅在數值更改時以天數差異更新它?我的意思是,每次獲得差異有什麼意義? – shahkalpesh 2010-02-13 20:02:12

+0

始終將存儲日期與今天進行比較......因此必須每天更新至少一次(這是一個選項) – 2010-02-13 20:06:06

回答

2

我不認爲用UDF tbh可以做很多事情 - 在運行時計算它在SQL中總是會在某種程度上產生影響。

所以,理想情況下(這可能不可能,因爲我不知道完整的圖片),我想我會做的是將WorkingDays編號存儲在您的表中,並在記錄創建時計算一次。如果這是不可能的(即創建記錄時,你沒有「結束日期」,因此必須使用「現在」來計算),那麼我會考慮每晚安排的工作去重新計算所有那些特定的記錄,以便每天更新 - 然後當輸入「結束日期」時,該記錄不會包含在此批量更新中。

這樣做的好處是,您將計算卸載到較安靜的時間段,並且每天只進行一次計算。查詢變得更加簡單和性能更高,因爲它可以從表中讀取WorkingDays編號。

如果這不是一個選項,那麼我會建議在前端進行計算,從數據庫中刪除命中。

+0

因爲計算總是基於今天,所以我需要每天分配一個值,而不是在記錄創建時(也許以及在創建記錄時初始化值),但請確保良好的通話。 – 2010-02-13 20:01:12

+0

@Simon - 我懷疑是這樣。但我認爲值得考慮夜間更新方法。每天更新一次,可以大大提高報告績效 - 特別是如果整天計算多次 – AdaTheDev 2010-02-13 20:05:57

0

有兩個問題在這裏:

  1. 計算的數量兩天之間的日期,
  2. 確定給定日期是否爲「營業日」。

第二類包括容易的,如「工作日」與「週末」,節假日(世俗,宗教,法律等)等

你需要同時解決。

第一個更容易,因爲關係數據庫將有幫助你的功能。這是第二個更難和更多變量,因爲它由地區和業務改變。

+0

我的要求比這更簡單,我不關心假期,基本上不包括週末....我的解決方案確實做到了這一點,我只是想確保我有在這裏錯過了一招,並且正在以最有效的方式執行解決方案。 – 2010-02-13 19:58:04

+0

聖誕節,新年等 - 不需要擔心這些?那麼這是一個更容易的問題。 – duffymo 2010-02-13 20:01:48

+0

目前還沒有,我只關心我對問題的解決方案的執行情況。 – 2010-02-13 20:04:56

相關問題