SQL-检查某个日期是否是该日期当月的第一次出现

SQL-检查某个日期是否是该日期当月的第一次出现,sql,sql-server,tsql,datetime,Sql,Sql Server,Tsql,Datetime,我有一些日期要用SQL过滤 我希望能够通过一个标志,表明保留从X日期到Y日期的每个月的第一个星期一 因此,本质上,我希望传递一个日期,并能够判断它是给定月份的第一个、第二个、第三个、第四个还是最后一个星期一(例如) 我已经过滤了月份和日期,我正在使用日期部分(日期,日期)检查日期是否15等逻辑。。如果第四个星期一也是最后一个星期一呢?你可以使用从下个月的第一个减去8天的技巧来确定它是否是最后一个星期一。非常感谢你的帮助。这很有效,但似乎只适用于周一?也许我不太清楚,但我只是以星期一为例。如果我删

我有一些日期要用SQL过滤

我希望能够通过一个标志,表明保留从X日期到Y日期的每个月的第一个星期一

因此,本质上,我希望传递一个日期,并能够判断它是给定月份的第一个、第二个、第三个、第四个还是最后一个星期一(例如)

我已经过滤了月份和日期,我正在使用
日期部分(日期,日期)
检查日期是否<8,然后1周<15 2周等等。。。。但这是不对的

所以我一直坚持的部分是
其中是datefirstofmonth(@date)
我应该从哪里开始编写函数
IsDateFirstOfMonth
? 非常感谢您的任何帮助

您可以这样做

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 @temp=@first
    while @temp<=@last
    begin
        insert into @table(StartDate,EndDate,DayName) values(@temp,@temp+6,datename(dw,@temp))
        set @temp=@temp +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 @last-@date<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
alter函数是datefirstofmonth(@date作为datetime)
返回整数
作为
开始
声明@first datetime,
@上次,
@临时日期时间,
@外观智力
声明@table table(Id int-identity(1,1),
开始日期时间,
EndDate日期时间,
DayName nvarchar(20),
行数(整数)
设置@first=dateadd(天,1天(@date),@date)
设置@last=dateadd(月,1,@first)-1
首先设置@temp=@first

对于此类问题,@temp通常更容易实现包含所需日期信息的表,并在该表上进行连接,并使用它进行过滤。即,使用以下信息创建一个表:

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。所以你不能指望第四个是最后一个

这个表实际上占用的空间非常小,大约是
日期的3个字节,TINYINT的1个字节,BIT的1个字节,所以它是3+1+1=5字节/天,1825字节/年,整个世纪178KB。所以,即使你需要几个世纪来涵盖所有可能的日期,我仍然是一张非常小的桌子。我粗略地说是因为索引结构、填充因子和其他一些东西会使表变得更大。如此小的表意味着SQL Server在执行查询时可以轻松地将整个表缓存在内存中,因此您的查询将运行得非常快

注意:通过添加新的
BIT
列,您可以扩展此表以满足其他需要,例如检查某一天是当月的最后一天,还是当月的最后一个或第一个工作日


非常有趣的链接,来自OP评论:

感谢您的帮助。 哈迪:你的回答很好,但我还是决定使用理货台

我在这里找到了一个很好的例子


再次感谢

检查一个月的日期是否小于8有什么问题?您是否试图确定
@date
是第一个星期一,还是在一个月的第一周内(即,是否在一年中的同一周内,是同一个月的第一个日期)?听起来你好像两个都想做。我有一个完整的约会清单。比如说从今天到年底的所有周一。我想选择每个月的第一个或第二个或第三个或第四个或最后一个星期一返回。因此,如果我使用>8或>15等逻辑。。如果第四个星期一也是最后一个星期一呢?你可以使用从下个月的第一个减去8天的技巧来确定它是否是最后一个星期一。非常感谢你的帮助。这很有效,但似乎只适用于周一?也许我不太清楚,但我只是以星期一为例。如果我删除周一的if检查并使用“2014年11月15日”运行它,我会得到2而不是3,因为这是11月的第三个周六。再次感谢你的帮助。另外,如果您不介意解释所有嵌套的DateDiff是如何工作的,那将非常感谢,也许我可以自己调试;)删除if(datename(dw,@date)='Monday'),那么它将在一周内工作所有天,但正如我在使用'2014年11月15日'运行它时所说,我得到了2,而不是预期的3,因为这是11月的第三个星期六。干杯,非常感谢你,因为我知道这是一个棘手的问题。对于select dbo,我似乎仍然有一些奇怪的行为,例如select dbo.IsDateFirstOfMonth('2014年12月24日')给出-1,而select dbo.IsDateFirstOfMonth('2014年12月5日')给出0。@user2329438我以完全不同的方式重新编写了函数,这一次,这个函数将花费整个月的时间,构建本月的周数,然后根据日期名称划分周数,最后将检查日期是否为最后一个,希望这次您的问题能够得到解决Hanks JotaBe,我同时发现了这篇文章,并决定按照您的建议进行操作