基于今天的日期范围

时间:2017-03-29 20:06:55

标签: sql sql-server sql-server-2012

我正在尝试编写一个存储过程,该过程将在每月的1日,8日,15日和22日由自动报告调用。

下面我有我目前正在尝试使用的代码,但如果在第一天运行,我会在@StartDate的行上收到错误Explicit conversion from data type int to date is not allowed.。但是我已经尝试评论该部分,我只是得到了相同的错误,但接下来是@StartDate。

我需要@StartDate和@EndDate才能根据当前运行报告的哪一天进行更改。

  • 1号需要从21号开始运行 上个月到上个月底。
  • 在8日,它必须是当月的第1个到第7个。
  • 在15日,它必须是当月的第8个到第14个。
  • 在22日,它必须是当月到21日的第15个。

    Declare @RunDate    date
    Declare @StartDate Date
    Declare @EndDate    Date
    
    Set  @RunDate = '3/1/2017'
    
    If (Day(@RunDate) = 1)
    Begin
    
    Set @StartDate  = Convert(Date,(Month(DATEADD(d,-1,@Rundate)) + '/21/' + Case When Month(@Rundate) = '1' Then Year(@RunDate) Else Year(DATEADD(yy,-1,@Rundate)) End),101)
    Set @EndDate    = Convert(date,DATEADD(ms,-3,DATEADD(mm,0,DATEADD(mm,DATEDIFF(mm,0,@Rundate),0))),101)
    
    End
    Else
    IF (Day(@RunDate) = 8)
    Begin
    
    Set @StartDate  = Convert(Date,(Month(@Rundate) + '/1/' + Year(@RunDate)),101)
    Set @EndDate    = Convert(Date,(Month(@Rundate) + '/7/' + Year(@RunDate)),101)
    
    End
    Else
    If (Day(@Rundate) = 15)
    Begin
    
    Set @StartDate  = Convert(Date,(Month(@Rundate) + '/8/' + Year(@RunDate)),101)
    Set @EndDate    = Convert(Date,(Month(@Rundate) + '/14/' + Year(@RunDate)),101)
    
    End
    Else
    If (Day(@Rundate) = 22)
    Begin
    
    Set @StartDate  = Convert(Date,(Month(@Rundate) + '/15/' + Year(@RunDate)),101)
    Set @EndDate    = Convert(Date,(Month(@Rundate) + '/21/' + Year(@RunDate)),101)
    
    End
    

我正在使用带有SSMS 2016前端的SQL Server 2012后端。如果这有帮助。

3 个答案:

答案 0 :(得分:2)

您可以将所有这些简化为:

Declare @RunDate date, @StartDate date, @EndDate date;
Set  @RunDate = '20170301';
If (Day(@RunDate) = 1)
Begin;
Set @StartDate = dateadd(day,20,dateadd(month, datediff(month, 0, @RunDate)-1, 0)) 
Set @EndDate   = dateadd(day,-1,dateadd(month, datediff(month, 0, @RunDate), 0)) 
End;
Else
If (Day(@RunDate) in (8,15,22))
Begin;
Set @StartDate = dateadd(day,Day(@RunDate)-8,dateadd(month, datediff(month, 0, @RunDate), 0))
Set @EndDate   = dateadd(day,Day(@RunDate)-2,dateadd(month, datediff(month, 0, @RunDate), 0))
End;

使用case替代,但不验证day()中的8,15,22

Declare @RunDate date, @StartDate date, @EndDate date;
Set  @RunDate = '20170328';

set @StartDate = case day(@RunDate)
    when 1 then dateadd(day,20,dateadd(month, datediff(month, 0, @RunDate)-1, 0)) 
    else dateadd(day,Day(@RunDate)-8,dateadd(month, datediff(month, 0, @RunDate), 0))
    end;

set @EndDate = case day(@RunDate)
    when 1 then dateadd(day,-1,dateadd(month, datediff(month, 0, @RunDate), 0)) 
    else dateadd(day,Day(@RunDate)-2,dateadd(month, datediff(month, 0, @RunDate), 0))
    end;

两者的rextester演示:http://rextester.com/CCUFI85069

答案 1 :(得分:0)

尝试更改代码以设置日期......

SET @StartDate = CONVERT(DATE, 
    CONCAT(MONTH(DATEADD(d, -1, @Rundate)),
    '/21/',
     IIF(MONTH(@Rundate) = '1', YEAR(@RunDate), YEAR(DATEADD(yy,  -1, @Rundate)))) , 101)

完整的代码看起来像这样......

Declare @RunDate    date
Declare @StartDate Date
Declare @EndDate    Date

Set  @RunDate = '3/1/2017'

If (Day(@RunDate) = 1)
Begin

Set @StartDate  = CONVERT(DATE, CONCAT(MONTH(DATEADD(d, -1, @Rundate)), '/21/',IIF(MONTH(@Rundate) = '1', YEAR(@RunDate), YEAR(DATEADD(yy,  -1, @Rundate)))) , 101)
Set @EndDate    = Convert(date,DATEADD(ms,-3,DATEADD(mm,0,DATEADD(mm,DATEDIFF(mm,0,@Rundate),0))),101)

End
Else
IF (Day(@RunDate) = 8)
Begin

Set @StartDate  = Convert(Date, CONCAT(Month(@Rundate) , '/1/' , Year(@RunDate)) ,101)
Set @EndDate    = Convert(Date, CONCAT(Month(@Rundate) , '/7/' , Year(@RunDate)) ,101)

End
Else
If (Day(@Rundate) = 15)
Begin

Set @StartDate  = Convert(Date, CONCAT(Month(@Rundate) , '/8/' , Year(@RunDate)) ,101)
Set @EndDate    = Convert(Date, CONCAT(Month(@Rundate) , '/14/' , Year(@RunDate)) ,101)

End
Else
If (Day(@Rundate) = 22)
Begin

Set @StartDate  = Convert(Date, CONCAT(Month(@Rundate) , '/15/' , Year(@RunDate)) ,101)
Set @EndDate    = Convert(Date, CONCAT(Month(@Rundate) , '/21/' , Year(@RunDate)) ,101)

END

SELECT @StartDate, @EndDate

你甚至可以隐藏重复的代码并创建一个简单的函数......

CREATE FUNCTION [dbo].[GetDateBasedOnStringNumber] (@num NVARCHAR(20), @RunDate DATE)
RETURNS DATE
WITH SCHEMABINDING AS
BEGIN
  DECLARE @retDate DATE
  SELECT  @retDate = Convert(Date, CONCAT(Month(@RunDate) , @num , Year(@RunDate)) ,101)

  RETURN @retDate ;
END;

然后使用这种模式......

SELECT @StartDate = dbo.GetDateBasedOnStringNumber('/1/', @RunDate)
SELECT @EndDate = dbo.GetDateBasedOnStringNumber('/7/', @RunDate)

答案 2 :(得分:0)

该错误是因为您尝试将integervarchar值一起添加。以此行为例:

Set @StartDate  = Convert(Date,(Month(DATEADD(d,-1,@Rundate)) + '/21/' + Case When Month(@Rundate) = '1' Then Year(@RunDate) Else Year(DATEADD(yy,-1,@Rundate)) End),101)

如果您细分计算的部分,则会有integer个月的值,一天varchar值和一年integer值。如果您尝试连接这些,则会收到错误消息:

  

消息245,级别16,状态1,行9转换时转换失败   varchar值' / 21 /'数据类型int。

您可以将integer值转换为varchar,这样就可以了。

建议使用内置的date函数而不是使用连接,这样就可以获得相同的结果:

DECLARE
    @RunDate DATE = '20170101'
,   @StartDate DATE
,   @EndDate DATE

IF DATEPART(DAY, @RunDate) = 1
    SELECT
        @StartDate = DATEADD(DAY, -(DATEPART(DAY, DATEADD(DAY, -1, @RunDate)) - 20), @RunDate)
    ,   @EndDate = DATEADD(DAY, -1, @RunDate)

SELECT
    @StartDate
,   @EndDate