劳动节与劳动节感恩节

问题描述 投票:0回答:6

我正在为我的仓库创建一个日历表。我将使用它作为所有日期字段的外键。

下面显示的代码创建表并填充它。 我能够弄清楚如何找到阵亡将士纪念日(五月的最后一个星期一)和劳动节(九月的第一个星期一)。

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

我很难确定感恩节(十一月最后一个完整周的星期四)。

编辑: 根据 John Sauer

的评论进行更正

感恩节是十一月的第四个星期四。 然而查了几年,发现原来也是11月最后一个完整周的星期四

sql-server t-sql data-warehouse
6个回答
16
投票

我很难确定感恩节(十一月最后一个完整周的星期四)。

11 月最后一个星期六 - 2


6
投票

以 11 月的最后一个星期六为例,减去两天;)


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 月的星期四吗?还有不到一周的时间吗?


0
投票

我们在数据库中使用一个简洁的标量值函数,我们可以调用它来确定日期是否为非工作日。我们手动添加观察假期的特殊日期。

创建函数:

CREATE FUNCTION [dbo].[NonWorkDay](@date as DATETIME)

RETURNS bit
AS

BEGIN
    if @date is not null
    begin
        -- Weekends
        if DATEPART(weekday, @date)=1 return 1 --Sunday
        if DATEPART(weekday, @date)=7 return 1 --Saturday
        -- JAN
        if month(@date)=1 AND day(@date)=1 return 1 -- New Years Day
        -- MAY
        if month(@date)=5 and DATEPART(weekday, @date)=2 and day(@date)>24 and day(@date)<=31 return 1 --Memorial Day
        -- JULY
        if month(@date)=7 AND day(@date)=4 return 1 -- July 4th
        -- SEP
        if month(@date)=9 and DATEPART(weekday, @date)=2 and day(@date)<=7  return 1--Labor Day
        -- NOV
        if month(@date)=11 and DATEPART(weekday, @date)=5 and day(@date)>21 and day(@date)<=28 return 1--Thanksgiving
        if month(@date)=11 and DATEPART(weekday, @date)=6 and day(@date)>22 and day(@date)<=29 return 1 -- Black Friday
        -- DEC
        if month(@date)=12 AND day(@date)=24 return 1 -- Christmas Eve
        if month(@date)=12 AND day(@date)=25 return 1 -- Christmas
        if month(@date)=12 AND day(@date)=31 return 1 -- NYE    

        -- Office Closed for Observed Holiday Dates
        if month(@date)=7 AND day(@date)=5 AND year(@date)=2021 return 1 -- 4th of July Observed for 2021
        if month(@date)=12 AND day(@date)=26 AND year(@date)=2022 return 1 -- Christmas Day observed for 2022
        if month(@date)=1 AND day(@date)=2 AND year(@date)=2023 return 1 -- New Years Day observed for 2023
        if month(@date)=7 AND day(@date)=3 AND year(@date)=2026 return 1 -- 4th of July Observed for 2026
        if month(@date)=7 AND day(@date)=5 AND year(@date)=2027 return 1 -- 4th of July Observed for 2027
    end
    return 0
END
GO

通话功能:

IF [dbo].[NonWorkDay](Getdate())= 0 -- If (not a NonWorkDay -ie not Sat or Sun)

0
投票

这应该可以解决问题:

declare @is_thanksgiving bit,
    @cur_date datetime = getdate()

select @is_thanksgiving = case when datename(month, @cur_date) = 'November'
        and datename(weekday, @cur_date) = 'Thursday'
        and day(@cur_date) between 22 and 28
    then 1 else 0 end

第四个星期四应该介于:

  • 22 日(如果该月的第一天是星期四……感恩节初),并且
  • 28 号(如果该月的第一天是星期五...感恩节晚些时候)

这与 Christian Pena 的答案非常相似,但我认为他的答案相差 1。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.