2016-09-19 53 views
0

基于日期行的变量量我有4个变量:插入在范围

@startDate 
@endDate 
@maxCourses 
@preferredCourseStartDay 

比方说,他们是:

Start Date - 1st Aug 2016 
End Date - 30th Sept 2016 
Max Courses - 5 
Start Day - Tuesday 

我需要从该日期范围的第一个星期二开始将5行插入临时表中。

输出样本:

02/08/2016 
09/08/2016 
16/08/2016 
23/08/2016 
30/08/2016 

任何帮助理解

+0

请出示样品输出 – TheGameiswar

+0

2016年2月8日 2016年9月8日 16/08/2016 23/08/2016 30/08/2016 – Dough

回答

2

下面是一个使用的CTE和窗函数的一种方法:

with n as (
     select row_number() over (order by (select null)) - 1 as n 
     from master..spt_values 
    ) 
select dte 
from (select dateadd(day, n.n, @startdate) as dte, 
      row_number() over (order by n.n) as seqnum 
     from n 
     where datename(weekday, dateadd(day, n.n, @startdate)) = @preferredCourseStartDay 
    ) x 
where seqnum <= @maxCourses 
order by dte; 

我毫无疑问,有一个简练和优雅的方式来查找给定数据之后或之后的第一个星期二。此方法避开该方法,只是在生成的所有日期中查找周二。请注意,这假定您的语言的国际化设置。

+0

我使用Azure和主..不支持spt_values,但我调整了这一点,并得到它的工作。感谢您的答复! – Dough

+0

@面团。 。 。这只是构建数字表的一种方法。只要有足够的行,任何表都会执行。 –

0
declare @startDate datetime = '8/1/2016' 
declare @endDate datetime = '9/30/2106' 
declare @maxCourses int = 5 
declare @preferredCourseStartDay varchar(16) = 'Tuesday' 

declare @wkDay int = case 
         when @preferredCourseStartDay = 'Sunday' then 0 
         when @preferredCourseStartDay = 'Monday' then 1 
         when @preferredCourseStartDay = 'Tuesday' then 2 
         when @preferredCourseStartDay = 'Wednesday' then 3 
         when @preferredCourseStartDay = 'Thursday' then 4 
         when @preferredCourseStartDay = 'Friday' then 5 
         when @preferredCourseStartDay = 'Saturday' then 6 
        end 



SELECT DATEADD(DAY,number+1,dateadd(dd,@wkDay - datepart(weekday,@startDate),@startDate)) [Date] 
FROM master..spt_values 
WHERE type = 'P' 
AND DATEADD(DAY,number+1,dateadd(dd,@wkDay - datepart(weekday,@startDate),@startDate)) <= dateadd(day,@maxCourses,dateadd(dd,@wkDay - datepart(weekday,@startDate),@startDate)) 
0

我不知道如果这些日子是每周或连续的,下面是如何处理这两种情况的例子。

DECLARE 
@StartDate date  = '20160801',-- - 1st Aug 2016 
@EndDate date  = '20160930', --30th Sept 2016 
@MaxCourses tinyint  = 5, 
@startDay varchar(10) = 'Tuesday'; 

-- if you need the next 5 tuesdays 
WITH 
E1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) x(x)), 
iTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 FROM E1 a, E1 b, E1 c), 
calendar(d) AS 
(
    SELECT TOP (DATEDIFF(DAY,@StartDate,@EndDate)) DATEADD(DAY,N,@startDate) 
    FROM itally 
) 
SELECT TOP(@MaxCourses) d 
FROM calendar 
WHERE DATENAME(WEEKDAY,d) = @startDay; 

-- if you need the next 5 days 
WITH 
E1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) x(x)), 
iTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1 FROM E1 a, E1 b, E1 c), 
calendar(N,d) AS 
(
    SELECT TOP (DATEDIFF(DAY,@StartDate,@EndDate)) N, DATEADD(DAY,N,@startDate) 
    FROM itally 
), 
md(d1) AS (SELECT MIN(d) FROM calendar WHERE DATENAME(WEEKDAY,d) = @startDay) 
SELECT TOP (@MaxCourses) d = DATEADD(day,N,d1) 
FROM calendar CROSS JOIN md;