2014-11-06 97 views
0

我有一些日期希望用SQL過濾。SQL - 檢查日期是否是該月當天第一次發生

我希望能夠通過一個標誌來說明從X日期到Y日期的所有月份的第一個星期一。

所以基本上,我想通過一個日期,並能夠告訴它是否是給定月份的第一個,第二個,第三個,第四個或最後一個星期一(例如)。

我已經過濾掉了幾個月和幾天,我目前正在使用DATEPART(DAY, thedate)檢查一天是否爲< 8然後是一週< 15 2周等....但這是不正確的。

所以我卡在的部分是Where IsDateFirstOfMonth(@date) 我在哪裏開始寫功能IsDateFirstOfMonth? 任何幫助非常讚賞

+4

有什麼不對的檢查月份的一天少於8? – 2014-11-06 21:21:46

+0

您是否試圖確定'@ date'是第一個星期一,還是在本月的第一個星期(即,是否在同一月的第一個日期的同一周)?這幾乎聽起來像你正在努力做到這一點。 – 2014-11-06 21:40:08

+0

那麼我有一個完整的日期列表。讓我們說從今天到今年年底的所有星期一。我希望可以選擇在每個月內返回第一或第二或第三或第四個星期一或最後一個星期一。所以如果我使用> 8或> 15等邏輯。它不會總是工作的第四或最後 – user2329438 2014-11-06 21:42:07

回答

0

你可以做到這一點

alter function IsDateFirstOfMonth(@date as datetime) 
returns int 
as 
begin 
    declare @first datetime, 
      @last datetime, 
      @temp datetime, 
      @appearance int 
    declare @table table(Id int identity(1,1), 
         StartDate datetime, 
         EndDate datetime, 
         DayName nvarchar(20), 
         RowNumber int) 
    set @first=dateadd(day,1-day(@date),@date) 
    set @last=dateadd(month,1,@first)-1 
    set @[email protected] 
    while @temp<[email protected] 
    begin 
     insert into @table(StartDate,EndDate,DayName) values(@temp,@temp+6,datename(dw,@temp)) 
     set @[email protected] +1 
    end  
    select @appearance=Nb 
    from(
    select StartDate,EndDate,DayName,row_number() over (partition by DayName order by StartDate) as Nb 
    from @table) t 
    where @date between t.StartDate and t.EndDate and datename(dw,@date)=t.DayName 

    if @[email protected]<7 
     set @appearance=-1 

    return @appearance 
end 



select dbo.IsDateFirstOfMonth('31 Dec 2014')  
    select dbo.IsDateFirstOfMonth('03 Nov 2014') -- result 1 (first) monday 
    select dbo.IsDateFirstOfMonth('10 Nov 2014') -- result 2 (second) 
    select dbo.IsDateFirstOfMonth('17 Nov 2014') -- result 3 (third) 
    select dbo.IsDateFirstOfMonth('24 Nov 2014') -- result -1 (last) .... here it will be the last monday 
    select dbo.IsDateFirstOfMonth('02 Nov 2014') -- result 1 (first) sunday 

希望這將幫助你

+0

非常感謝你的幫助。這工作得很好,但只爲星期一好像?也許我不太清楚,但我只是以星期一爲例。如果我刪除如果檢查星期一,並運行'2014年11月15日'我得到2而不是3,因爲它是11月的第三個星期六。再次感謝您的幫助。如果你不介意解釋所有嵌套的datediffs是如何工作的,這將是最值得讚賞的,也許我可以調試自己;) – user2329438 2014-11-06 23:04:09

+0

刪除if(datename(dw,@ date)='Monday'),那麼它將工作一週中的所有日子 – Monah 2014-11-06 23:05:14

+0

我做到了,但就像我說的,當我運行'2014年11月15日'我得到2,而不是預期的3,因爲它是11月第三個星期六.cheers – user2329438 2014-11-06 23:09:20

1

對於這樣的問題,它通常更容易實現一個表所需的最新信息和加入表中,並使用它過濾。即創建一個表,這個信息:

CREATE TABLE Dates(
    Date DATE PRIMARY KEY CLUSTERED, 
    PositionInMoth TINYINT, 
    LastInMonth BIT) 

然後使用任何你想要的方式填寫此表。我想你會用一個簡單的臨時應用程序很容易地做到這一點,但你也可以使用T-SQL腳本來創建它。

然後,您只需要將此表與此表連接起來,並使用PositionInMoth或LastInMonth列進行過濾。您還可以將其用作查找表來輕鬆實現所需的功能。

順便說一下,不要忘記,有多個月有一個給定的一天的第五個例子,例如,2014年12月有5個星期一,5個星期二和5個星期三。給定motnh中有5個實例的天數爲:本月的天數 - 28,例如12月份的31-28 = 3。所以你不能指望第4天是最後一天。

該表確實佔用很少的空間,大致,爲DATE 3個字節,對於TINYINT 1個字節,爲BIT 1個字節,所以它的3 + 1 + 1 =每天5個字節,1,825字節每年和178千兆整個世紀。所以,即使你需要幾個世紀才能涵蓋所有可能的日期,我仍然是一個非常小的桌子。我說大致爲,因爲索引結構,填充因子和其他一些東西會使表格稍微大一些。如此小的表格意味着SQL Server在執行查詢時可以輕鬆地將整個表格緩存在內存中,因此您的表格將運行得非常快。

注:您可以通過添加新BIT

非常展開該表格涵蓋如檢查等方面的需求,如果一天是在本月的最後一個,或最後一個或第一個工作日,在一個月內,有趣的鏈接,從OP評論:CALENDAR TABLES IN T-SQL

+0

謝謝JotaBe,我在這段時間找到了這篇文章,並決定與你的建議一起去http://blog.aware.co.th/calendar-tables-在-T-SQL / – user2329438 2014-11-07 16:38:10

相關問題