我陷入了一个问题。需要你的帮助。
我有表tblEventCalendarEvents
id name start_date end_date rec_type
891 Bob Lehman 2012-05-01 2099-02-01 0_2_1_1
892 Bob Lehman 2012-11-01 2099-02-01 1_4_3_1
893 Bob Lehman 2012-05-03 2099-02-01 0_0_2_2
我想做这样的任务。我想要这样的记录,如果今天between startdate and enddate
也基于rec类型。
在RecType中,归档值为0_2_1_1
之类的存储意味着此事件在每个第二个月,第一周和第三天重复。
因此,如果事件在2012-05-01开始意味着2012年5月1日,那么现在该事件在这样的日期重复,这样的日期将重现,那么它将每两个月重复一次,所以下个月是7月,1周和3日日期意味着下一个重复日期是2012-07-03,2012年7月3日。
所以它将重复
2012/07/01
2012/09/02
2012/11/04
2013/01/06
答案 0 :(得分:2)
最后我得到了答案。
USE [Database]
GO
/****** Object: UserDefinedFunction [dbo].[getNextDay] Script Date: 12/28/2012 17:10:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE function [dbo].[getNextDay](@SDate datetime, @Rec varchar(max))
returns datetime
as
BEGIN
--Find the next day based on Condition
Declare @SecArg varchar(max)
Declare @NYear varchar(max)
Declare @NMonth varchar(max)
Declare @NWeek varchar(max)
Declare @NDay varchar(max)
select @NYear = substring(@rec,0,CHARINDEX('_',@rec))
SET @REC = SUBSTRING(@rec,CHARINDEX('_',@rec)+1,LEN(@REC))
select @NMonth = substring(@rec,0,CHARINDEX('_',@rec))
SET @REC = SUBSTRING(@rec,CHARINDEX('_',@rec)+1,LEN(@REC))
select @NWeek = substring(@rec,0,CHARINDEX('_',@rec))
SET @REC = SUBSTRING(@rec,CHARINDEX('_',@rec)+1,LEN(@REC))
Declare @NewDate datetime
set @NewDate = @SDate
if (@NYear != 0 or @NYear != '')
begin
set @SDate = DateAdd(Year,Convert(int,@Nyear),@SDate)
end
if (@NMonth != 0 or @NMonth != '')
begin
set @SDate = DateAdd(Month,Convert(int,@NMonth),@SDate)
end
return Convert(varchar, dbo.getWeekDay(Convert(int,@NWeek),Convert(Int,@rec),DATEADD(dd,-(DAY(@SDate)-1),@SDate)),120)
end
现在我创建了另一个函数getWeekDay,用于查找特定月份的特定周的日期
USE [Database]
GO
/****** Object: UserDefinedFunction [dbo].[getWeekDay] Script Date: 12/28/2012 17:15:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE function [dbo].[getWeekDay]( @var_weeknum int, @var_weekday int, @var_date datetime)
returns datetime
as
BEGIN
declare @cnt int
declare @startDay int
declare @DayDiffrence int
declare @ReturnDate datetime
set @cnt = 1
set @startday = datepart(dw, dateadd(mm, datediff(mm, 0, @var_Date),0))
set @DayDiffrence = @var_weekday - @startday
set @ReturnDate = dateadd(mm, datediff(mm, 0, @var_date),0)
if(@DayDiffrence > 0)
begin
set @ReturnDate = dateadd(d,@DayDiffrence,@ReturnDate)
set @ReturnDate = dateadd(wk,@var_weeknum - 1,@ReturnDate)
end
else
begin
set @ReturnDate = dateadd(d,7 - (@DayDiffrence * -1),@ReturnDate)
set @ReturnDate = dateadd(wk,@var_weeknum - 1,@ReturnDate)
end
return @ReturnDate
end
现在终于通过单一查询得到了答案
select dbo.getNextDay('2012-07-01','0_2_3_3')
In this my date is 2012-07-01
my condition is every 0 year, 2 month, and 3rd week and 3rd dayofweek.
so this will return 2012-09-18
感谢www.google.com和blog.sqlauthority.com 还要感谢我的Stackoverflow朋友.... :)
答案 1 :(得分:0)
首先,我强烈建议对rec_type字段重新构建(规范化)表,而不是将varchar设置为四个tinyint字段,如下所示: rec_y rec_m rec_w rec_d
因此,只需按如下方式编写用户定义函数:
CREATE FUNCTION GetNextEvent
(
@curevent datetime, @rec_y tinyint, @rec_m tinyint, @rec_w tinyint, @rec_d tinyint, @end_date datetime
)
RETURNS datetime AS
BEGIN
DECLARE @nextevent datetime
set @nextevent=DATEADD(DAY,@rec_d,DATEADD(WEEK,@rec_w,DATEADD(MONTH,@rec_m,DATEADD(YEAR,@rec_y,@curevent))))
if @nextevent>@end_date set @nextevent=null
RETURN @nextevent
END
然后你可以编写一个Cursor循环来获取所有的事件日期,只要它们小于end_date,这是根据你的要求在创建和更新时保存在另一个表的数据库中,或者是根据请求查看和计算的。