2016-09-19 58 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;