T-SQL CTE,计算上一行值
T-SQL CTE, calculation on Previous Row value
我有一个 CTE returns 一组行取决于以下方式的模式:
模式Table
(从开始日期开始为下周一创建 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 是一个包含递增数字列表的 table。
现在,当我 运行 SELECT 当然 CTE returns 总是相同 "next 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 和其他功能。
也许你可以稍微简化一下。
我无法与您的 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)
Returns -- 我展示了所有字段以便您更好地可视化结果
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 = 每周,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)
我有一个 CTE returns 一组行取决于以下方式的模式:
模式Table (从开始日期开始为下周一创建 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 是一个包含递增数字列表的 table。
现在,当我 运行 SELECT 当然 CTE returns 总是相同 "next 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 和其他功能。
也许你可以稍微简化一下。
我无法与您的 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)
Returns -- 我展示了所有字段以便您更好地可视化结果
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 = 每周,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)