我有一个CTE,它根据模式以下列方式返回一组行:
模式表 (从开始日期开始为下一个星期一创建100行)
| |
|--Id--|--Start Date--|--Count--|--Days--|
| |
|--AB--| 01-01-2000 | 100 | Monday |
| |
我有功能,通过传递开始日期计算下一个发生日:
dbo.fx_get_next_occurrence(@startDate DATETIME, @days VARCHAR)
为了生成行,我使用CTE如下:
WITH Occurrences_CTE(Num, Id, StartDate)
AS
(
SELECT
SP.n
,F.Id
,dbo.fx_get_next_occurrence(F.Days, F.StartDate)
FROM
#RecurrencePattern AS F
INNER JOIN
dbo.Numbers AS SP
ON SP.n between 1 and F.[Count]
)
dbo.numbers 是一个包含增量数字列表的表。
现在,当我运行SELECT当然,CTE总是返回相同的"下一个日期"因为Date永远不会增加,所以这个SELECT:
SELECT
CTE.Id, CTE.Num, CTE.StartDate
FROM
Occurrences_CTE CTE
生成如下结果:
| |
|--Id--|--Num--|--Start Date--|
| |
|--AB--|--001--|--01-03-2000--|
|--AB--|--002--|--01-03-2000--|
|--AB--|--003--|--01-03-2000--|
|--AB--|--004--|--01-03-2000--|
|--AB--|--005--|--01-03-2000--|
现在,尽管函数按预期工作,但我如何从CTE获取之前计算的日期行,以便我可以将此日期传递给我的函数从前一个开始到下一个可用的日期?将CTE加入到自身,然后呢?
在SQL 2012和2014上午,我可以使用LAG和其他功能。
答案 0 :(得分:1)
也许你可以稍微简化一下。
我无法与您的UDF对话,但可能没有必要,因为您很快就会看到。 cteKeyDate产生的不仅仅是必要的,但是当您加入数据时会过滤结果。
您可能还注意到我在您的样本数据中添加了另一行,该行发生在星期一和星期五,但只计数为50
Declare @Table table (id varchar(25),StartDate Date,Count int,Days varchar(25))
Insert into @Table values
('AB','2000-01-01',100,'Monday'),
('CD','2000-01-01',50,'Monday,Friday')
Declare @MinDate Date = (Select min(StartDate) from @Table)
Declare @MaxCntr Int = (Select max(Count) from @Table)
Declare @MaxDate Date = DateAdd(wk,@MaxCntr+10,@MinDate)
;With cteKeyDate As (
Select KeyDate = @MinDate,KeyDOW = DateName(WEEKDAY,@MinDate)
Union All
Select KeyDate = DateAdd(DD, 1, df.KeyDate) ,KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyDate))
From cteKeyDate DF
Where DF.KeyDate <= @MaxDate
)
Select *
From (
Select A.ID
,A.StartDate
,A.Count
,A.Days
,KeyDate
,KeyDow
,RowNr = Row_Number() over (Partition By A.ID Order By B.KeyDate)
from @Table A
Join cteKeyDate B on B.KeyDate>=A.StartDate and Charindex(KeyDOW,Days)>0
) Final
Where RowNr<=Count
Option (maxrecursion 32767)
返回 - 我显示了所有字段,因此您可以更好地可视化结果
ID StartDate Count Days KeyDate KeyDow RowNr
AB 2000-01-01 100 Monday 2000-01-03 Monday 1
AB 2000-01-01 100 Monday 2000-01-10 Monday 2
AB 2000-01-01 100 Monday 2000-01-17 Monday 3
AB 2000-01-01 100 Monday 2000-01-24 Monday 4
...
AB 2000-01-01 100 Monday 2001-11-05 Monday 97
AB 2000-01-01 100 Monday 2001-11-12 Monday 98
AB 2000-01-01 100 Monday 2001-11-19 Monday 99
AB 2000-01-01 100 Monday 2001-11-26 Monday 100
CD 2000-01-01 50 Monday,Friday 2000-01-03 Monday 1
CD 2000-01-01 50 Monday,Friday 2000-01-07 Friday 2
CD 2000-01-01 50 Monday,Friday 2000-01-10 Monday 3
.....
CD 2000-01-01 50 Monday,Friday 2000-06-16 Friday 48
CD 2000-01-01 50 Monday,Friday 2000-06-19 Monday 49
CD 2000-01-01 50 Monday,Friday 2000-06-23 Friday 50
答案 1 :(得分:1)
为Every添加了一个字段。所以1 =每周,2每隔一周,依此类推。
以此为旋转
Declare @Table table (id varchar(25),StartDate Date,Count int,Days varchar(25),Every int)
Insert into @Table values
('AB','2000-01-01',50,'Monday',2),
('CD','2000-01-01',50,'Monday,Friday',2)
Declare @MinDate Date = (Select min(StartDate) from @Table)
Declare @MaxCntr Int = (Select max(Count) from @Table)
Declare @MaxDate Date = DateAdd(wk,@MaxCntr+10,@MinDate)
;With cteKeyDate As (
Select KeyDate = @MinDate,KeyDOW = DateName(WEEKDAY,@MinDate),KeyWeek = datepart(WK,@MinDate)
Union All
Select KeyDate = DateAdd(DD, 1, df.KeyDate) ,KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyDate)), KeyWeek= DatePart(WK,DateAdd(DD, 1, df.KeyDate))
From cteKeyDate DF
Where DF.KeyDate <= @MaxDate
)
Select *
From (
Select A.ID
,A.StartDate
,A.Count
,A.Days
,A.Every
,KeyDate
,KeyDow
,KeyWeek
,RowNr = Row_Number() over (Partition By A.ID Order By B.KeyDate)
from @Table A
Join cteKeyDate B on B.KeyDate>=A.StartDate and Charindex(KeyDOW,Days)>0
) Final
Where RowNr<=Count and (KeyWeek) % (Every) = 0
Option (maxrecursion 32767)