2009-07-29 5 views
5

私は倉庫用のカレンダーテーブルを作成しています。これをすべての日付フィールドの外部キーとして使用します。労働日対。感謝祭

以下に示すコードは、テーブルを作成し、それを設定します。私はメモリアルデー(5月最後の月曜日)と労働日(9月最初の月曜日)を見つける方法を見つけ出すことができました。

SET NOCOUNT ON 

DROP Table dbo.Calendar 
GO 
Create Table dbo.Calendar 
(
    CalendarId    Integer NOT NULL, 
    DateValue    Date NOT NULL, 
    DayNumberOfWeek   Integer NOT NULL, 
    NameOfDay    VarChar (10) NOT NULL, 
    NameOfMonth    VarChar (10) NOT NULL, 
    WeekOfYear    Integer NOT NULL, 
    JulianDay    Integer NOT NULL, 
    USAIsBankHoliday  Bit  NOT NULL, 
    USADayName    VarChar (100) NULL, 
) 
ALTER TABLE dbo.Calendar ADD CONSTRAINT 
    DF_Calendar_USAIsBankHoliday DEFAULT 0 FOR USAIsBankHoliday 
GO 
ALTER TABLE dbo.Calendar ADD CONSTRAINT 
    DF_Calendar_USADayName DEFAULT '' FOR USADayName 
GO 

Declare @StartDate DateTime = '01/01/2000' 
Declare @EndDate DateTime = '01/01/2020' 

While @StartDate < @EndDate 
Begin 
    INSERT INTO dbo.Calendar 
    (
     CalendarId, 
     DateValue, 
     WeekOfYear, 
     DayNumberOfWeek, 
     NameOfDay, 
     NameOfMonth, 
     JulianDay 
    ) 
    Values 
    (
     YEAR (@StartDate) * 10000 + MONTH (@StartDate) * 100 + Day (@StartDate), --CalendarId 
     @StartDate,     -- DateValue 
     DATEPART (ww, @StartDate), -- WeekOfYear 
     DATEPART (dw, @StartDate), -- DayNumberOfWeek 
     DATENAME (dw, @StartDate), -- NameOfDay 
     DATENAME (M, @StartDate), -- NameOfMonth 
     DATEPART (dy, @StartDate) -- JulianDay 
    ) 

    Set @StartDate += 1 
End 

--=========================== Weekends 
-- saturday and sunday 
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Weekend, ' WHERE DayNumberOfWeek IN (1, 7) 


--=========================== Bank Holidays 
-- new years day 
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'New Year''s Day, ' WHERE (CalendarId % 2000) IN (101) 

-- memorial day (last Monday in May) 
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Memorial Day, ' 
WHERE 1=1 
AND CalendarId IN 
    (
     SELECT MAX (CalendarId) 
     FROM dbo.Calendar 
     WHERE MONTH (DateValue) = 5 
     AND DATEPART (DW, DateValue)=2 
     GROUP BY YEAR (datevalue) 
    ) 

-- independence day 
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Independence Day, ' WHERE (CalendarId % 2000) IN (704) 

-- labor day (first Monday in September) 
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Labor Day, ' 
WHERE 1=1 
AND CalendarId IN 
    (
     SELECT MIN (CalendarId) 
     FROM dbo.Calendar 
     WHERE MONTH (DateValue) = 9 
     AND DATEPART (DW, DateValue)=2 
     GROUP BY YEAR (datevalue) 
    ) 

-- thanksgiving day (fourth Thursday in November) 
UPDATE dbo.Calendar 
SET USAIsBankHoliday = 1, 
    USADayName += 'Thanksgiving Day, ' 
WHERE 1=1 
AND CalendarId IN 
    (
     SELECT Max (CalendarId) 
     FROM dbo.Calendar 
     WHERE MONTH (DateValue) = 11 
     AND DATEPART (DW, DateValue)=5 
     GROUP BY YEAR (datevalue) 
    ) 

-- christmas 
UPDATE dbo.Calendar SET USAIsBankHoliday = 1, USADayName += 'Christmas Day, ' WHERE (CalendarId % 2000) IN (1225) 

--=========================== Other named days 
-- new years eve 
UPDATE dbo.Calendar SET USADayName += 'New Year''s Eve, ' WHERE (CalendarId % 2000) IN (1231) 

-- christmas eve 
UPDATE dbo.Calendar SET USADayName += 'Christmas Eve, ' WHERE (CalendarId % 2000) IN (1224) 

-- boxing day 
UPDATE dbo.Calendar SET USADayName += 'Boxing Day, ' WHERE (CalendarId % 2000) IN (1226) 

--=========================== Remove trailing comma 
UPDATE dbo.Calendar SET USADayName = SubString (USADayName, 1, LEN (USADayName) -1) WHERE LEN (USADayName) > 2 

SELECT * FROM dbo.Calendar 

私は感謝祭の日(木曜日の最後の完全な週の11月)に困惑しています。

編集:ジョン・ザウアーによってコメントに基づいて 修正

感謝祭は11月の第四木曜日です。しかし、数年前からチェックすると、私は(それは私が感謝祭の日考え出すに困惑していますまた、11月

+0

お待ちください。七面鳥を幸せにします。 – balpha

+2

ラマダンの始まりも挑戦的です。 – Smandoli

+0

そして、良い金曜日と復活祭があります。 – RobH

答えて

16

の最後の完全な週の木曜日であることが判明していることがわかり木曜日11月の最後のFULL週の)。 11月の

先週の土曜日 - 2

6

11月の最終土曜日に乗り、2日を引く、それはから一致する日付を見つけることが、時には良いでしょう、複雑なアルゴリズムについては

3
WITH cal AS 
     (
     SELECT CAST('2009-30-11' AS DATETIME) AS cdate 
     UNION ALL 
     SELECT DATEADD(day, -1, cdate) 
     FROM cal 
     WHERE cdate >= '2009-01-11' 
     ) 
SELECT TOP 1 DATEADD(day, -2, cdate) 
FROM cal 
WHERE DATEPART(weekday, cdate) = 6 

)巨大な単一価値式を構築しようとするよりも、

は詳細のための私のブログにこの記事を参照してください。

1
declare @thedate datetime 
set @thedate = '11/24/2011' 

select 1 
where datepart(dw, @thedate) = 5 and datepart(m, @thedate) = 11 AND (datepart(dd, @thedate) - 21) between 0 and 6 

は、11月の日木曜日ですし、そこに残りの一週間未満です。

関連する問題