2011-07-25 80 views
1

我如何計算在過去五次工作日內即週一至週五。我目前的腳本得到最後一個星期一的日期,但是我不能得到最後一個星期五的日期。請幫助計算工作日 - 週一至週五在TSQL

declare @StartDate datetime 
declare @EndDate datetime 


--Calculate date range for report 

select @EndDate = Cast(convert(char(10), getdate(), 101)+' 00:00:00' as datetime) 
select @StartDate = DateAdd(d, -7, @EndDate) 
select @EndDate = Cast(convert(char(10), getdate(), 101)+' 23:59:59' as datetime) 

select @StartDate startdate 
select @EndDate enddate 
+1

這個問題是非常相似的http://stackoverflow.com/questions/4025047/tsql-function-to-calculate-30-working-days-date-from-a-specified-date-sql-服務器 –

+0

@Brian Dishaw是的,也許它看起來像那個問題,但給定的代碼不是很好,答案不被接受。順便說一句,6個問題,你還沒有接受任何答案 –

回答

2

日期部分爲您提供了一種簡單的方法來獲得工作日:

SET DATEFIRST 1 -- monday is first day of the week 
SELECT DATEPART(weekday, '20110725') 
-- result is 1 

有關更多信息,請參見T-SQL Date functionsSET DATEFIRST

使用平日,你可以工作了多少天前的最後一個星期一和星期五是和(就像你現在做的)使用「ADDDATE」來計算的。

請注意,你應該使用DATEDIFF這種類型的日期範圍內選擇。如果您選擇了23:59:59之前的所有內容,那麼總有一些機會會遺漏一些記錄。例如23:59:59.001超出範圍,但它仍然在同一天。使用DATEDIFF您可以測試它是否在同一天,放棄時間部分。不需要費心鑄造繩子,增加時間和鑄造回來。

0

這兩個問題:

可能有一定的幫助。

雖然如果您已經知道如何找到上個星期一,您可以通過使用DATEADD()函數在星期一日期中添加4天來輕鬆找到相應的星期五。例如:

SELECT @EndDate = DATEADD(DAY, 4, @StartDate) 
0

這都是相對於今天的日子吧?

因此,找出什麼是今天DATEPART(weekday, getdate())

然後把它轉換成調整變量 - 例如:

declare @adjustment int 
set @adjustment = CASE DATEPART(weekday, getdate()) WHEN 'MONDAY' THEN 0 WHEN 'TUESDAY' THEN 1, ...END 

那麼接下來的週一你想會是今天 - 7 - @adjustment
...和星期五你想要星期一+ 5

Declare @myMonday smalldatetime, 
     @myFriday smalldatetime 
set @myMonday = getdate() - 7 - @adjustment 
set @myFriday = @myMonday + 5 
1

答案比人們假設更復雜。你需要的是前5天回去找到第一個星期一,之後的第一個星期五。你可以使用@@ datefirst,一個計算或'set firstdate 1'。我不喜歡使用最後一個,因爲它不能在函數中完成。正如你所看到的,我使用了這個計算,@@ datefirst同樣好。

假設你要到週五最後一組週一的是過去。這個查詢會得到。如果你信任你目前的星期一,你可以加5天,扣1分(我不相信它,它只有在你運行在星期一的查詢返回的最後一個星期一)。

在我的SQL,我的目標不是爲了簡單起見,我的目標的有效性。

DECLARE @getdate datetime = dateadd(day, cast(getdate() as int), 0) 
-- the 'Declare' can also be written like this thanks to @Andriy M 
--DECLARE @getdate = CAST(GETDATE() - 0.5 AS int) 
SELECT @getdate - 5 - CAST(@getdate- 5 as int) % 7 monday, 
dateadd(minute, -1, @getdate) - CAST(@getdate- 5 as int) % 7 friday 

結果:

Monday    Friday 
2011-07-18 0:00:00 2011-07-22 23:59:00 

*第一溶液放一天假@AndriyM指出了這一點,它已經解決了。


答到@Andriy中號

出於某種原因,行動比我預想的不同。我無法解釋,但試試這個

select cast(dateadd(day, cast(getdate() as int) - .5, 0) as datetime), 
cast(dateadd(day, cast(getdate() as int), 0) as datetime), 
cast(dateadd(day, cast(getdate() as int) + .5, 0) as datetime) 
在上午的最後2場具有相同的價值

,在晚上的第一場2具有相同的值。我和你一樣驚訝,我希望我能解釋它。正是在這裏 http://data.stackexchange.com/stackoverflow/query/new

+0

你是不是在'cast(getdate()爲int)'中使用' - 0.5',爲什麼?你知道'cast(datetime as int)'* rounds * datetime而不是截斷它,不是嗎? –

+0

我的意思是'cast(cast('20110725 18:00:00'作爲日期時間)作爲int)'不會返回與'cast(cast('20110725 06:00:00'作爲日期時間)相同的int) '。 –

+0

@Andriy M答案是我的腳本 –

0
DECLARE @my int 
DECLARE @myDeduct int 
DECLARE @day INT 
DECLARE @mydate DATETIME 

SET @mydate = '2012-08-01' 

SET @myDeduct = 0 
SET DateFirst 1 -- Set it monday=1 (value) 

--Saturday and Sunday on the first and last day of a month will Deduct 1 
IF (DATEPART(weekday,(DATEADD(dd,-(DAY(@mydate)-1),@mydate))) > 5) 
SET @myDeduct = @myDeduct + 1 

IF (DATEPART(weekday,(DATEADD(dd,-(DAY(DATEADD(mm,1,@mydate))),DATEADD(mm,1,@mydate)))) > 5) 
SET @myDeduct = @myDeduct + 1 

SET @my = day(DATEADD(dd,-(DAY(DATEADD(mm,1,@mydate))),DATEADD(mm,1,@mydate))) 

select (((@my/7) * 5 + (@my%7)) - @myDeduct) as Working_Day_per_month 
+0

雖然這確實會產生一個有趣的導致有人在那裏有興趣知道,它實際上不回答上面提出的問題。再看看上面.. ;-) –

0

測試我會扔我的帽子環太。 :-)

DECLARE @Date  datetime = '01/11/2015' 
DECLARE @StartDate datetime = DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6) -- MONDAY 
DECLARE @EndDate datetime = DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6) -- FRIDAY 

     SELECT '@Date'  as Variable ,CONVERT(date, @Date)  as DateValue ,DATENAME(dw, @Date)  as DayOfTheWeek 
UNION SELECT '@StartDate' as Variable ,CONVERT(date, @StartDate) as DateValue ,DATENAME(dw, @StartDate) as DayOfTheWeek 
UNION SELECT '@EndDate' as Variable ,CONVERT(date, @EndDate) as DateValue ,DATENAME(dw, @EndDate) as DayOfTheWeek 

-- Variable DateValue DayOfTheWeek 
-- ---------- ---------- ------------ 
-- @Date  2015-01-11 Sunday 
-- @StartDate 2015-01-05 Monday 
-- @EndDate 2015-01-09 Friday 

獎勵:在這裏,您可以使用相同的技術生成5個工作日的快速表。

SELECT DATENAME(dw, DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6))) as DayOfTheWeek 
     ,    DATEADD(d, TT.DaysToAdd, DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date - 6) % 7)), @Date - 6)) as DateValue 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT 

-- DayOfTheWeek     DateValue 
-- ------------------------------ ----------------------- 
-- Monday       2015-01-05 00:00:00.000 
-- Tuesday      2015-01-06 00:00:00.000 
-- Wednesday      2015-01-07 00:00:00.000 
-- Thursday      2015-01-08 00:00:00.000 
-- Friday       2015-01-09 00:00:00.000 

這裏有一個解釋:

1)首先,我們需要知道的日期從開始我們的評測。在這個例子中,我們選擇使用週日,1月11日,2015年

DECLARE @Date2 datetime = '01/11/2015' 

1B)這裏是一個不錯的一週的日子越來越名字的獎金技術,給定一個日期值

SELECT @Date2 as DateValue, DATENAME(dw, @Date2) as DayOfTheWeek 

2)接下來,我們需要知道的確定性(根據美國日曆)什麼星期的某一天是

  • 數字1至7注:1899年12月31日是1900年1月1日之前的第一個星期日,這是MINIMUM值f或SmallDateTime數據類型。
  • 注意:是的,你可以這樣使用DATEPART(DW,@date)更簡單,但它給出的是不確定性,某些服務器環境可能有不同的配置
  • 結果:1 =星期日| 2 =星期一| 3 =星期二| 4 =星期三| 5 =星期四| 6 =星期五| 7 =週六

    SELECT ((DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7) + 1) [DayOfWeek Deterministic (Based on US)] 
    

3)現在,給定任意日期,你應該有確定的週一,鑑於本週

SELECT DATEADD(d, (1 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7)), @Date2) as [Monday Day of the Week - Deterministic (Based on US)] 

4)現在,以確定的方式,給定任意日期,你應該確定週五爲某一週

SELECT DATEADD(d, (5 - (DATEDIFF(d, CAST('1899.12.31' AS datetime), @Date2) % 7)), @Date2) as [Monday Day of the Week - Deterministic (Based on US)] 

5)的最後日期操縱技術的一個確定的方式,我們需要的是知道如何進入一個星期的平日之前的第一個星期。例如,如果我們在星期天,我們從中減去1天,那麼我們到達星期六,這使我們在前一週,這是平日的第一個整週。另外,如果我們也從星期一減去1天,那麼它只會讓我們到週日,而不是前一週,所以減去1天是不夠的。另一方面,如果我們在星期六並且減去7天,它將使我們超過前一週的平日,進入前一週,這太過分了。下面是分析的一個縮減,找出可以減去的神奇數字,這將在一週中的任何一天工作。正如你可以看到下面,一個神奇的數字是6。

--           DAYS TO SUBTRACT 
-- Day of the Week  - 0  - 1  - 2  - 3  - 4  - 5  - 6  - 7 
-- ===============  ==== ==== ==== ==== ==== ==== ==== ==== 
-- Sunday    Bad  Good Good Good Good Good Good Good 
-- Monday    Bad  Bad  Good Good Good Good Good Good 
-- Tuesday    Bad  Bad  Bad  Good Good Good Good Good 
-- Wednesday   Bad  Bad  Bad  Bad  Good Good Good Good 
-- Thursday    Bad  Bad  Bad  Bad  Bad  Good Good Good 
-- Friday    Bad  Bad  Bad  Bad  Bad  Bad  Good Good 
-- Saturday    Good Good Good Good Good Good Good Bad 

獎金)如果你想擁有所有平日裏小桌子,然後你想還使用了快速零基礎「理貨表」。有很多方法可以做到這一點,所以選擇你的味道。這裏有一些。

SELECT * FROM (SELECT 0 as DaysToAdd UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) as TT 
SELECT * FROM (SELECT TOP 5 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM sys.all_columns a CROSS JOIN sys.all_columns b) as TT 
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 as DaysToAdd FROM (VALUES(0),(0),(0),(0),(0)) a(n)) as TT 
相關問題