如何根据运行日期查询2个不同的日期范围

时间:2012-08-06 17:59:36

标签: sql sql-server vb.net

我正在制作一个使用Windows调度程序自动运行的程序。我想做的是将程序设置为在每个月的1日和16日运行。如果程序在1日运行。我想让查询在上个月运行...例如,如果今天是8月的第一个,我希望它运行7/1/12 - 7/31/12。如果我在16日运行该程序,我希望它将当前月份的查询运行到15日。例如,如果是8/16,我希望程序运行8/1/12 - 8/15/12的查询。完成此任务的最佳方法是什么?我是否使用2个单独的程序将查询附加到正确的日期范围?一个计划在每个月的第一天运行,一个在16日运行?我如何获得日期范围和年份,因为它取决于它运行的月份/年...我的查询是:

SELECT        Store_Number, Invoice_Number, Invoice_Date, Extended_Price, Warranty_Amount, Quantity_Sold, Invoice_Detail_Code
FROM            Invoice_Detail_Tb
WHERE        (Warranty_Amount > 0) AND (Invoice_Date BETWEEN CONVERT(DATETIME, '2012-08-01 00:00:00', 102) AND CONVERT(DATETIME, '2012-08-05 00:00:00', 102))
ORDER BY Store_Number, Invoice_Date

4 个答案:

答案 0 :(得分:3)

尝试8/1/20128/16/2012作为日期。它返回您想要查看的值:

declare @date datetime = '8/16/2012', @start datetime, @end datetime

if datepart(dd, @date) = 1
begin
  set @start = dateadd(mm, -1, @date)
  set @end = dateadd(dd, -1, @date)
end
else
begin
  set @start = dateadd(dd, -15, @date)
  set @end = dateadd(dd, -1, @date)
end

select @start, @end

调整它可以相当容易,以便根据任何输入日期动态计算正确的开始和结束日期 - 这样您就可以在月份的任何时间运行它。

答案 1 :(得分:2)

这应该很简单,让我为你举一些例子。 我真的认为这应该是一个预定的任务,而不是多个任务。 在一天结束时更容易指出并查看一个计划任务(一个程序) 然后去挖掘多个程序,看看可能有什么不对。

可以使用SQL Server代理(在作业部分下)安排任务。该作业可以指向一个存储过程。

在此过程中,您可以执行简单的if else if逻辑。

IF DAY(GetDate()) = 1    - 在这里编码

ELSE IF DAY(GETDATE()) = 16    - 在这里编码

DAY(date_expression)返回datetime列中的日期。具有讽刺意味的是,如果由于某种原因需要那些功能,则有MONTH和YEAR功能。其余的很简单,如果你是在这个月的第一个日期,然后执行每月查询从几个月的第一天到下个月的第一天 - 1,这将成为:

SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))

否则,如果它在16日命中,你可以在第一天运行,直到月份的一半。

答案 2 :(得分:1)

如果您在视图中有查询,可以使用:

where
    Invoice_Date between
    (
        case
            when datepart(dd, getdate()) = 1 then dateadd(mm, -1, getdate())
            else dateadd(dd, -15, getdate())
        end
    )
    and
    (
        case
            when datepart(dd, getdate()) = 1 then dateadd(dd, -1, getdate())
            else dateadd(dd, -1, getdate())
        end
    )

更新:忽略时间

(我知道它看起来很难看。)

where
    Invoice_Date between
    (
        case
            when datepart(dd, dateadd(dd, datediff(dd, 0, getdate()), 0)) = 1 then dateadd(mm, -1, dateadd(dd, datediff(dd, 0, getdate()), 0))
            else dateadd(dd, -15, dateadd(dd, datediff(dd, 0, getdate()), 0))
        end
    )
    and
    (
        case
            when datepart(dd, dateadd(dd, datediff(dd, 0, getdate()), 0)) = 1 then dateadd(dd, -1, dateadd(dd, datediff(dd, 0, getdate()), 0))
            else dateadd(dd, -1, dateadd(dd, datediff(dd, 0, getdate()), 0))
        end
    )

答案 3 :(得分:0)

这就是我通常做的事情。您的存储过程应如下所示:

declare
  @today  datetime ,
  @dtFrom datetime ,
  @dtThru datetime

------------------------------------------------------
-- get the current date, discarding the time component
------------------------------------------------------
set @today  = convert(datetime,convert(varchar,current_timestamp,112),112) -- get todays date, discarding the time component

---------------------------------------------------------------------------------------------------------------------------------------------------
-- determine the start/end dates of the query period.
--
-- if the query date (@today) is in the 1st half of the month (1st - 15th), the query range is the entire preceding month
-- if the query date (@today) is in the last half of the month (16 - 31st), the query range is the 1st of the current month up to the current date
---------------------------------------------------------------------------------------------------------------------------------------------------
if ( datepart(day) < 16 )
  begin
    set @dtThru = dateadd(day,   - datepart(day, @today  ) , @today  ) -- set the end   date to the last day of the previous  month
    set @dtFrom = dateadd(day, 1 - datepart(day, @dtThru ) , @dtThru ) -- set the start date to the first day of the previous month
  end
else
  begin
    set @dtfrom = dateadd(day, 1  - datepart(day, @today) , @today ) -- set the start date to the first day of the current month
    set @dtThru = @today
  end

----------------------------------------------------------------------------------------------------------------------
-- finally, adjust the start/end times to cover the entire gamut of date/time values for the month
--
-- We don't have to modify @dtFrom at all: we know its time component is 00:00:00.000 already. However, we want
-- @dtThru to have a time component of 23:59:59.997, due to SQL Server's broken way of counting time -- any time value
-- higher than that (e.g., '23:59.59.999') is 'rounded up' to start-of-day (00:00.00.000), the next day. Brilliant!
--   
----------------------------------------------------------------------------------------------------------------------
set @dtThru = dateadd(ms, -3 , dateadd(day,1,@dtThru) )

--------------------------------
-- return the data to the caller
--------------------------------
SELECT Store_Number        ,
       Invoice_Number      ,
       Invoice_Date        ,
       Extended_Price      ,
       Warranty_Amount     ,
       Quantity_Sold       ,
       Invoice_Detail_Code
FROM Invoice_Detail_Tb id
WHERE Warranty_Amount > 0
  AND Invoice_Date BETWEEN @dtFrom AND @dtThru
ORDER BY Store_Number ,
         Invoice_Date

如果您没有使用存储过程,则可以使用参数化查询完成相同的操作。计算所需的两个DateTime值。将占位符放在select语句中('@ dtFrom'和'@dtThru')。执行查询时,将两个DateTime值作为SqlParameter对象传递,其名称与占位符匹配。