Reputation: 21
Looking to fill a table (SQL Server) on the basis of given data:
StartData - 04/1/2019, EndData - 04/30/2019, Interval = 2
Skip complete one week on the basis of interval. Like shown expected result.
Output:
04/01/2019
04/02/2019
04/03/2019
04/04/2019
04/05/2019
04/06/2019
04/07/2019
** Skip 7 days
04/15/2019
04/16/2019
04/17/2019
04/18/2019
04/19/2019
04/20/2019
04/21/2019
** Skip 7 days
04/29/2019
04/30/2019
Upvotes: 0
Views: 84
Reputation: 1455
Achieved this using CTE
with t0(i) as (select 0 union all select 0 union all select 0 union all select 0 union all select 0 union all select 0),
t1(i) as (select 0 from t0 a, t0 b),
n(i) as (select row_number()over(order by i) from t1),
tbl1 as ( select 0 i, dateadd(month, datediff(month,0,getdate()),0) daysOfMonth
union all
select n.i , dateadd(day,n.i, dateadd(month, datediff(month,0,getdate()),0)) daysOfMonth from n where n.i between 0 and 6 ),
tbl2 as (select n.i , dateadd(day,n.i, dateadd(month, datediff(month,0,getdate()),0)) daysOfMonth from n where n.i between datepart(day,dateadd(day,7,(select max(daysOfMonth) from tbl1))) and dateadd(day,7,datepart(day,dateadd(day,6,(select max(daysOfMonth) from tbl1))))),
tbl3 as (select n.i , dateadd(day,n.i, dateadd(month, datediff(month,0,getdate()),0)) daysOfMonth from n where n.i between datepart(day,dateadd(day,7,(select max(daysOfMonth) from tbl2))) and dateadd(day,-1,datepart(day,eomonth(getdate()))))
select * from tbl1
union all
select * from tbl2
union all
select * from tbl3
In above query the CTE table t0, t1 and n
are used to generste numbers.
Table tbl
will fetch the first 7 days of the month.
Table tbl2
will skip the next 7 days and will fetch next week. this is done using datediff
and dateadd
function.
Table tbl3
will again skip 7 days and will pull all dates till the end of the month.
Output
Upvotes: 1
Reputation: 81930
With the function provided in your previous question
Example
Declare @Date1 date = '2018-04-01'
Declare @Date2 date = '2018-04-30'
Declare @Freq int = 2
Declare @OffDays varchar(50) = 'Thursday' -- Try 'Saturday,Sunday'
Select B.RetVal
From [dbo].[tvf-Range-Date](@Date1,@Date2,'WK',1) A
Cross Apply [dbo].[tvf-Range-Date](A.RetVal,DateAdd(DAY,6,A.RetVal),'DD',1) B
Where A.RetSeq % @Freq = 1
and B.RetVal<=@Date2
Returns
The Function if Interested
CREATE FUNCTION [dbo].[tvf-Range-Date] (@R1 datetime,@R2 datetime,@Part varchar(10),@Incr int)
Returns Table
Return (
with cte0(M) As (Select 1+Case @Part When 'YY' then DateDiff(YY,@R1,@R2)/@Incr When 'QQ' then DateDiff(QQ,@R1,@R2)/@Incr When 'MM' then DateDiff(MM,@R1,@R2)/@Incr When 'WK' then DateDiff(WK,@R1,@R2)/@Incr When 'DD' then DateDiff(DD,@R1,@R2)/@Incr When 'HH' then DateDiff(HH,@R1,@R2)/@Incr When 'MI' then DateDiff(MI,@R1,@R2)/@Incr When 'SS' then DateDiff(SS,@R1,@R2)/@Incr End),
cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a, cte1 b, cte1 c, cte1 d, cte1 e, cte1 f, cte1 g, cte1 h ),
cte3(N,D) As (Select 0,@R1 Union All Select N,Case @Part When 'YY' then DateAdd(YY, N*@Incr, @R1) When 'QQ' then DateAdd(QQ, N*@Incr, @R1) When 'MM' then DateAdd(MM, N*@Incr, @R1) When 'WK' then DateAdd(WK, N*@Incr, @R1) When 'DD' then DateAdd(DD, N*@Incr, @R1) When 'HH' then DateAdd(HH, N*@Incr, @R1) When 'MI' then DateAdd(MI, N*@Incr, @R1) When 'SS' then DateAdd(SS, N*@Incr, @R1) End From cte2 )
Select RetSeq = N+1
,RetVal = D
From cte3,cte0
Where D<=@R2
)
/*
Max 100 million observations -- Date Parts YY QQ MM WK DD HH MI SS
Syntax:
Select * from [dbo].[tvf-Range-Date]('2016-10-01','2020-10-01','YY',1)
Select * from [dbo].[tvf-Range-Date]('2016-01-01','2017-01-01','MM',1)
*/
Upvotes: 0
Reputation: 978
remove -- to un-comment select statement, I have printed the result, you can select as well.
DECLARE @StartDate datetime ='01-Apr-2019',
@EndDate datetime ='30-Apr-2019',
@Interval int = 2
DECLARE @dt datetime = @StartDate,
@count int = 1
WHILE (@dt <= @EndDate)
BEGIN
print @dt
--Select @dt
IF @count % 7 = 0
BEGIN
SET @Interval = @Interval - 1
SET @dt = dateAdd(day, 8, @dt);
PRINT '** Skip 7 days'
--SELECT '** Skip 7 days'
END
ELSE
BEGIN
SET @dt = dateAdd(day, 1, @dt);
END
SET @count = @count + 1
END
Upvotes: 0
Reputation: 3585
This is very simple using a tally table starting with zero.
DECLARE @StartDate date = '20190401',
@EndDate date = '20190430',
@interval int = 2;
WITH
E(n) AS(
SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
SELECT a.n FROM E a, E b
),
E4(n) AS(
SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
SELECT TOP(DATEDIFF( dd, @StartDate, @EndDate) + 1)
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) -1
FROM E4
)
SELECT DATEADD( DD, n, @StartDate)
FROM cteTally
WHERE (n/7 + 1)% @interval = 1;
This of course can be converted into an inline table-valued function to combine performance and ease of use.
CREATE FUNCTION getDateListWithIntervals(
@StartDate date,
@EndDate date,
@interval int
)
RETURNS TABLE
AS RETURN
WITH
E(n) AS(
SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0))E(n)
),
E2(n) AS(
SELECT a.n FROM E a, E b
),
E4(n) AS(
SELECT a.n FROM E2 a, E2 b
),
cteTally(n) AS(
SELECT TOP(DATEDIFF( dd, @StartDate, @EndDate) + 1)
ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) -1
FROM E4
)
SELECT DATEADD( DD, n, @StartDate) calDate
FROM cteTally
WHERE (n/7 + 1)% @interval = 1;
Upvotes: 2