2012-01-25 44 views
0

我在嘗試更新SQL報告存儲區的WHERE子句以檢查給定日期是否落在下一次類的發生之前。類有StartDate,每週在同一天發生一次。鑑於StartDate,我如何才能找到一週中的下一天?在SQL中查找下一個星期幾

E.G.如果開始日期是2012年1月18日星期三,並且我在截至今天的2012年1月26日運行此報告,則需要查找2/1/2012,這是1/26後的下個星期三。如果開始日期是星期四的1/19,並且我今天運行了該報告,則該公式應該在今天的1/26週四給我。

下面是SQL排序的想法:

SELECT * 
FROM tbl_Class cs 
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID 
WHERE ... 
AND sce.StartDate < [Find date of next class after @AsOfDate using cs.StartDate] 

回答

1

下面是我想出了一些示例SQL。 3次迭代,所以你可以按照我的結局。第三次迭代應該是可以通過將列名替換爲變量來併入WHERE子句中的。

設置:

DECLARE @Startdate DATETIME,@currentdate datetime 
SET @Startdate = '1-26-2012' 
SET @Currentdate = '1-23-2012' 

--This section just normalizes it so you can use 7 as the interval 
--The offset depends on your current setting for DATEFIRST, U.S. English default is 7, Sunday. 
-- see http://msdn.microsoft.com/en-us/library/ms187766.aspx 
DECLARE @StartDateWorkingDayOfWeek int,@CurrentDateWorkingDayOfWeek int 
SELECT @StartDateWorkingDayOfWeek =(DATEPART(weekday,@Startdate)-2) 
SELECT @CurrentDateWorkingDayOfWeek=(DATEPART(weekday,@Currentdate)-2) 

迭代#1

--Iteration 1 
IF @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek 
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 7,@StartDateWorkingDayOfWeek) 
else 
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 0,@StartDateWorkingDayOfWeek) 

迭代#2

--Iteration 2 
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 

CASE WHEN @StartDateWorkingDayOfWeek < @CurrentDateWorkingDayOfWeek 
    then 7 
    ELSE 0 
    end 

    ,@StartDateWorkingDayOfWeek) 

迭代#3

--iteration 3 
SELECT DATEADD(DAY,DATEDIFF(DAY,0,@Currentdate)/7*7 + 

CASE WHEN (DATEPART(weekday,@Startdate)-2) < (DATEPART(weekday,@Currentdate)-2) 
    then 7 
    ELSE 0 
    end 

    ,(DATEPART(weekday,@Startdate)-2)) 

帽尖這篇文章: http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3

+0

'DATEPART(WEEKDAY' [取決於'@@ DATEFIRST'(http://stackoverflow.com/a/5984859/73226)再次 –

+0

我的美國/英國爲中心的煩躁來襲!謝謝,馬丁。我會更新。 – TetonSig

+0

我想指出同樣的事情。減2假設@@ datefirst設置爲7.有了這個前提我認爲這是有效的。在閱讀你提供的鏈接來理解你的文章,我想我找到了另一個解決方案,它消除了對@@ datefirst的依賴,並且不需要條件語句。非常感謝您的介紹和鏈接。使用哪一個可能歸結爲個人偏好。 – xr280xr

0

這就是我想出了感謝TetonSig和他提到的這個鏈接:http://www.sqlmag.com/article/tsql3/datetime-calculations-part-3

我們可以得到當前日期的前一週的週一獨家的日期( @AsOfDate)像這樣:

SELECT DATEADD(day, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0); 

這將獲得天數在1/1/1900和@AsOfDate之間的天數。/7 * 7將其轉換爲整週,然後將其添加回1/1/1900(星期一)以獲取@AsOfDate之前的星期一。 -1使其不包含@AsOfDate。沒有減1,如果@AsOfDate在星期一,它將被計爲「前一個」星期一。

接下來筆者表明,要獲得包容下週一,我們只需要添加7到以前的獨家配方星期一:

SELECT DATEADD(d, DATEDIFF(day,0, @AsOfDate-1) /7*7, 0)+7; 

瞧!我們現在已經在@AsOfDate或之後獲得了第一個星期一。唯一的問題是,在我的情況下,上面的星期一(0)是一個移動的目標。我需要第一個[DayOfWeek]由班級日期決定,而不是第一個星期一。我需要換出ClassDayOfWeek計算上述0:

DATEADD(d, DATEDIFF(d, [ClassDayOfWeek], @AsOfDate-1)/7*7, [ClassDayOfWeek])+7 

我想計算ClassDayOfWeek不依賴於或具有惹DATEFIRST設置@@。所以,我計算出它相對於基準日:

DATEDIFF(d, 0, StartDate)%7 

這爲週一,6給出了0太陽,所以我們現在可以插在了[ClassDayOfWeek。我應該指出,這個0-6的值是以int表示的日期1/1/1900-1/7/1900。

DATEADD(d, DATEDIFF(d, DATEDIFF(d, 0, StartDate)%7, @AsOfDate-1)/7*7, DATEDIFF(d, 0, StartDate)%7)+7 

而且在每個問題用途:

SELECT * 
FROM tbl_Class cs 
INNER JOIN tbl_Enrollment sce ON cs.pk_ClassID = sce.fk_ClassID 
WHERE ... 
AND sce.StartDate < DATEADD(d, 
          DATEDIFF(d, 
            DATEDIFF(d, 0, cs.StartDate)%7, 
            @AsOfDate-1)/7*7, 
          DATEDIFF(d, 0, cs.StartDate)%7)+7 
0

我得出一個簡單的case語句的答案。
在你的情況下,@targetDOW將是該課程的一週中的一天。

DECLARE @todayDOW INT = DATEPART(dw, GETDATE()); 
DECLARE @diff INT = (@targetDOW - @todayDOW); 

SELECT 
    CASE 
     WHEN @diff = 0 THEN GETDATE() 
     WHEN @diff > 0 THEN DATEADD(d,@diff,GETDATE()) 
     WHEN @diff < 0 THEN DATEADD(d,@diff + 7,GETDATE()) 
    END;