【问题标题】:Add Particular day, year, month, week in particular date using sql server使用sql server在特定日期添加特定的日、年、月、周
【发布时间】:2012-12-28 08:53:22
【问题描述】:

我被困在一个查询中。需要你的帮助。

我有表 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 也基于记录类型。

在 RecType Filed 中存储的值类似于 0_2_1_1 表示此事件每隔一个月、第一周和第三天重复一次。

因此,如果事件开始于 2012 年 5 月 1 日意味着 2012 年 5 月 1 日,那么现在该事件在满足重复条件的日期重复,那么它将每两个月重复一次,所以下个月是 7 月、第 1 周和第 3 周天意味着下一个重复日期是 2012-07-03 2012 年 7 月 3 日。

所以它会重复

2012/07/01
2012/09/02
2012/11/04
2013/01/06

【问题讨论】:

  • 无论您使用哪种 DBMS,这都将是非常复杂的。可以办到;这样做不会很有趣。简单地解析符号month_n_w_d_#no 很麻烦。尚不清楚year_n_x_y_#no 版本中这些字段的含义(每个第 n 年的第 x 个月和该月的第 y 天?)。您的问题可以有用地省略“created_date”和“updated_date”列,因为它们对问题无关紧要,并且会避免水平滚动条(隐藏关键列)。您也可以省略“url”列。
  • @JonathanLeffler 现在在 rec_type 字段中再次检查我的问题,现在数据如 (year_month_week_day) 这意味着数据将以这种方式重复。如果 rec_type 为 0_2_1_1 则输出数据将在每 2 个月、第一周和第一天重复一次
  • 对于0_2_1_1,这意味着每两个月,第一周和第一天,对吗?所以在你的例子中,它应该是2012/07/012012/09/01等等?
  • @techdo 是的,但在最后一个参数中是指一周中的那一天而不是日期,所以就像如果 1 则为星期日,2 则为星期一......n 以此类推 7意味着星期六....
  • 你的问题是“我想要这样的记录,如果今天在 startdate 和 enddate 之间也基于记录类型。”是否意味着如果两个条件都满足,任务必须发生?

标签: sql sql-server sql-server-2008 tsql sql-server-2005


【解决方案1】:

我终于得到了答案。

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.comblog.sqlauthority.com 还要感谢我的 Stackoverflow 朋友.... :)

【讨论】:

    【解决方案2】:

    首先,我强烈建议为 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
    

    然后,您可以编写一个游标循环来获取所有事件日期,只要它们小于 end_date 根据您在创建和更新时保存在另一个表的数据库中或根据请求查看和计算的要求。

    【讨论】:

      猜你喜欢
      • 2018-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多