2009-08-18 41 views
1

我似乎在詢問很多SQL問題。 (我通常會寫一個程序來對數據進行排序到報告表,但是在那是不可能的時刻,並且需要使用SQL來完成)SQL - WHERE子句在下一個工作日返回結果

問題 我需要返回結果的where子句下一個工作日。即01/01/01週一,下一個工作日將是02/01/01的星期二,這可以通過簡單的日期添加來實現。然而在05/01/01的星期五,下一個工作日是08/01/01星期一。是否有內置的東西可以幫助輕鬆應對?

感謝您的建議。

回答

2

你可以用一個簡單的一天檢查做到這一點,加3幾天而不是一個,如果它是一個星期五。不過,你是否需要考慮公衆假期?

+0

理想情況下是,但如果它太複雜,那不是重要。 – Audioillity 2009-08-18 12:04:07

+0

具有固定日期的簡單PublicHolidays表將很容易選擇;展開@ Pinal的UDF(來自@ Vinko的回答),以便爲每場比賽將日期加1(無論朝哪個方向)。更詳細的假期設計可能是不必要的。 – devstuff 2009-08-18 12:15:29

+0

當我第一次想到時,它的簡單得多,報告只在週一天運行/創建。所以我需要做的就是制定出如果星期五加3天,否則我加1。 – Audioillity 2009-08-19 13:29:52

4

關鍵是要使用DATEPART(weekday,@date)函數,它將返回星期幾,所以如果是星期六或星期日,只需在當前日期中添加一到兩個即可獲得所需結果。

您可以創建用戶定義函數這樣做很容易,例如Pinal Dave有這個

CREATE FUNCTION dbo.udf_GetPrevNextWorkDay (@dtDate DATETIME, @strPrevNext VARCHAR(10)) 
RETURNS DATETIME 
AS 
BEGIN 
DECLARE @intDay INT 
DECLARE @rtResult DATETIME 
SET @intDay = DATEPART(weekday,@dtDate) 
--To find Previous working day 
IF @strPrevNext = 'Previous' 
IF @intDay = 1 
SET @rtResult = DATEADD(d,-2,@dtDate) 
ELSE 
IF @intDay = 2 
SET @rtResult = DATEADD(d,-3,@dtDate) 
ELSE 
SET @rtResult = DATEADD(d,-1,@dtDate) 
--To find Next working day 
ELSE 
IF @strPrevNext = 'Next' 
IF @intDay = 6 
SET @rtResult = DATEADD(d,3,@dtDate) 
ELSE 
IF @intDay = 7 
SET @rtResult = DATEADD(d,2,@dtDate) 
ELSE 
SET @rtResult = DATEADD(d,1,@dtDate) 
--Default case returns date passed to function 
ELSE 
SET @rtResult = @dtDate 
RETURN @rtResult 
END 
GO 
+1

一個小的改進是使用BIT類型而不是VARCHAR作爲方向,並且對於「next」和0 f有1個或「之前」,避免了第三種情況的需要。 – devstuff 2009-08-18 12:11:19

+0

從國際化的角度來看,這個UDF也可以採用日曆或地區代碼來查找適當的星期幾定義 - 請參閱http://en.wikipedia.org/wiki/Workweek – devstuff 2009-08-18 12:18:35

0

你可以用一個簡單的case語句來做到這一點。

select case when datepart(dw, getdate()) >= 6 then getdate() + (9 - datepart(dw, getdate())) else getdate() + 1 end 
3
CREATE FUNCTION dbo.uf_GetNextWorkingDay (@givenDate DATETIME) 
RETURNS DATETIME 
AS 
BEGIN 

    DECLARE @workingDate DATETIME 

    IF (DATENAME(dw , @givenDate) = 'Friday') 
     BEGIN 
      SET @workingDate = DATEADD(day, 3, @givenDate) 
     END 
    ELSE IF (DATENAME(dw , @givenDate) = 'Saturday') 
     BEGIN 
      SET @workingDate = DATEADD(day, 2, @givenDate) 
     END 
    ELSE 
     BEGIN 
      SET @workingDate = DATEADD(day, 1, @givenDate) 
     END 

    RETURN @workingDate 
END 

一篇好文章http://ryanfarley.com/blog/archive/2005/02/14/1685.aspx

0

你需要的是一個日曆表。如果你需要考慮週末以外的其他假期,那麼下一個工作日就不那麼簡單了。該表基本上只包含兩列Date和一個整數字段,指示它是否爲工作/非工作日 - 但也可以有其他列,例如四分之一等。

此表每年填充一次,然後根據需要進行維護。獲得下一個工作日的結果就像這樣的查詢一樣簡單。

SELECT field1,filed2 from your table T where your date_Field = (SELECT min(date) From calendar table where WorkingDay = 1 and date > GetDate()) 

/P

0

這個怎麼樣事端?

select * from table 
where (date = dateadd(dd,1,@today) and datepart(weekday,@today) not in (6,0)) --its not friday or saturday 
or (date = dateadd(dd,2,@today) and datepart(weekday,@today) = 0) -- its saturday 
or (date = dateadd(dd,3,@today) and datepart(weekday,@today) = 6) --its friday 

日期屬性應該有相同的時間@Today否則你必須

1

所有信貸之間也使用Cashif - 我修改了他對包括假期表(tblHolidays與日期字段HolDate),它非常輕便 - 如果你足夠幸運,可以每年大約10行!

我的版本返回date類型(我發現它更容易處理)。我也不止一次地運行 - 如果星期四是你的開始日,星期五是假期,那麼你必須再增加2天才能到達星期一(或下一個工作日)。然後檢查以確保下一週不會從假期開始。

CREATE FUNCTION [dbo].[GetNextWorkingDay] (@givenDate DATE) 
RETURNS DATE 
AS 
BEGIN 
    DECLARE @workingDate DATETIME 
    IF (DATENAME(dw , @givenDate) = 'Friday') 
    BEGIN 
     SET @workingDate = DATEADD(day, 3, @givenDate) 
    END 
    ELSE IF (DATENAME(dw , @givenDate) = 'Saturday') 
    BEGIN 
     SET @workingDate = DATEADD(day, 2, @givenDate) 
    END 
    ELSE 
    BEGIN 
     SET @workingDate = DATEADD(day, 1, @givenDate) 
    END 

    while ((Select count(*) from tblHolidays where holdate = @workingDate) > 0) 
    begin 
     set @workingDate = dateadd(dd,1,@WorkingDate) 
    end 
    -- if adding a day makes it a Saturday, add 2 more to get to Monday (and test to make sure the week doesn't start with a holiday) 
    IF (DATENAME(dw , @workingDate) = 'Saturday') 
    BEGIN 
     SET @workingDate = DATEADD(day, 2, @workingDate) 
    END 


    while ((Select count(*) from tblHolidays where holdate = @workingDate) > 0) 
    begin 
     set @workingDate = dateadd(dd,1,@WorkingDate) 
    end 
    RETURN @workingDate 
END 

...當然你應該重構所以代碼不重複,幷包括一個while子句重複只需要多次,以達到一個工作日,但我有一個截止日期......這將是另一個更少忙碌的一天。

1

這裏就是我做了一個一次性的應用程序:

 WHILE EXISTS (SELECT * FROM Holidays WHERE CONVERT(VARCHAR, HolidayDate,101) = CONVERT(VARCHAR,@DateVariable 101) OR DATENAME(WEEKDAY, @DateVariable)='SATURDAY' OR DATENAME(WEEKDAY, @DateVariable)='SUNDAY') 
     BEGIN 
      SET @DateVariable = DateAdd(day,1,@DateVariable) 
      PRINT @DateVariable -- If you want 
     END 

需要注意的是,我們的Holidays表存儲了所有節假日,在過去和今後幾年。

+0

我很喜歡這個。漂亮,簡單而優雅 – user853710 2016-04-06 12:41:51

0

上面已經基本回答了,但花了我一段時間纔得到它,我想也許這會幫助別人。使用簡單的CASE-WHEN。

這是一個檢查,以找出哪些天是工作日

DATEPART(dw, date) -> MON through FRI = 1,2,3,4,5 SAT = 6,  SUN = 7 

這種情況下,WHEN:

CASE 
    WHEN DATEPART(weekday, date) <= 5 THEN date  -- weekdays, no change 
    WHEN DATEPART(weekday, date) = 6 THEN date + 2 -- SAT + 2 = MON 
    WHEN DATEPART(weekday, date) = 6 THEN date + 1 -- SUN + 1 = MON 
END AS 'WEEKDAY_DATES' 

檢查,如果語句實際上只讓你平日:

CASE 
    WHEN DATEPART(weekday, date) <= 5 THEN DATENAME(weekday, date) 
    WHEN DATEPART(weekday, date) = 6 THEN DATENAME(weekday, date + 2) 
    WHEN DATEPART(weekday, date) = 6 THEN DATENAME(weekday, date + 1) 
END AS 'WEEKDAY_NAMES' 
相關問題