将 WHILE 转换为 CROSS APPLY
Converting WHILE to CROSS APPLY
我有一个标量函数,我正在将其转换为 TVF。
在标量函数中,我有以下 while
语句:
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
当我将其放入 TVF 时,我使用 CROSS APPLY
(在转换方面得到了一些帮助)并将其转换为以下代码:
CROSS APPLY (
VALUES(DATEADD(DAY, 30 * CEILING(( IIF(CAST(GETDATE() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0) + DATEDIFF(DAY, CA1.ReviewDueDate, GETDATE()) ) / 30.0), CA1.ReviewDueDate))
) CA2(ReviewDueDate)
转换部分我不是很清楚
我了解到 @ReviewDate < getdate()
时需要在 @ReviewDate
中添加 30 天。
当我试图理解转换后的 CROSS APPLY
代码时,我有点迷茫。
现在对我来说最难的部分是:
我还有两个 while 循环,如下所示:
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(Month, 6, @ReviewDueDate)
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(YEAR, 1, @ReviewDueDate)
所以我必须转换它才能在 CROSS APPLY
中使用它。
我不太清楚find while循环是怎么转换的,所以纠结其他两个
感谢任何帮助解释第一次转换的帮助。
如果有人可以帮助转换其他两个,那也很有帮助。
您本身不需要 cross apply
。显然它只是用来能够从多个地方引用计算表达式。
cross apply
中的公式直接计算出你需要添加多少个30天的chunk到@ReviewDueDate
,这样就超过了getdate()
:
- 取
@ReviewDueDate
和今天之间的天差。
- 如果
@ReviewDueDate
的时间大于今天的时间,则再加上一天。
- 将结果天数除以
30.0
以确保它不是 integer division。
- 四舍五入。这是您需要添加的 30 天区块数。
- 乘以 30 得到天数。
这不能很好地转换为 non-day 间隔,例如月或年。例如,这个:
DATEADD(month, 6 * CEILING(( IIF(CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0) + DATEDIFF(month, CA1.ReviewDueDate, getdate()) ) / 6.0), CA1.ReviewDueDate);
将是错误的,因为如果今天的日期在同一个月并且 CA1.ReviewDueDate
s 的时间不大于今天的时间,那么 return CA1.ReviewDueDate
未修改天。
所以除了 months/years:
你还需要调整天数的差异
DATEADD(
month,
6 * CEILING( (IIF( (day(getdate()) > day(CA1.ReviewDueDate) or CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME)), 1, 0) + DATEDIFF(month, CA1.ReviewDueDate, getdate())) / 6.0 ),
CA1.ReviewDueDate
)
DATEADD(
year,
1 * CEILING( (IIF( (month(getdate()) > month(CA1.ReviewDueDate) or day(getdate()) > day(CA1.ReviewDueDate) or CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME)), 1, 0) + DATEDIFF(year, CA1.ReviewDueDate, getdate())) / 1.0 ),
CA1.ReviewDueDate
)
所有这些都严格假设 CA1.ReviewDueDate
总是小于 getdate()
。如果不是,您想将整个事情包装到另一个处理这种情况的 case when ... end
中,并在今天已经过去时做一些不同的事情。
我有一个标量函数,我正在将其转换为 TVF。
在标量函数中,我有以下 while
语句:
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(DAY, 30, @ReviewDueDate)
当我将其放入 TVF 时,我使用 CROSS APPLY
(在转换方面得到了一些帮助)并将其转换为以下代码:
CROSS APPLY (
VALUES(DATEADD(DAY, 30 * CEILING(( IIF(CAST(GETDATE() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0) + DATEDIFF(DAY, CA1.ReviewDueDate, GETDATE()) ) / 30.0), CA1.ReviewDueDate))
) CA2(ReviewDueDate)
转换部分我不是很清楚
我了解到 @ReviewDate < getdate()
时需要在 @ReviewDate
中添加 30 天。
当我试图理解转换后的 CROSS APPLY
代码时,我有点迷茫。
现在对我来说最难的部分是:
我还有两个 while 循环,如下所示:
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(Month, 6, @ReviewDueDate)
WHILE @ReviewDueDate < getdate()
SET @ReviewDueDate = DATEADD(YEAR, 1, @ReviewDueDate)
所以我必须转换它才能在 CROSS APPLY
中使用它。
我不太清楚find while循环是怎么转换的,所以纠结其他两个
感谢任何帮助解释第一次转换的帮助。
如果有人可以帮助转换其他两个,那也很有帮助。
您本身不需要 cross apply
。显然它只是用来能够从多个地方引用计算表达式。
cross apply
中的公式直接计算出你需要添加多少个30天的chunk到@ReviewDueDate
,这样就超过了getdate()
:
- 取
@ReviewDueDate
和今天之间的天差。 - 如果
@ReviewDueDate
的时间大于今天的时间,则再加上一天。 - 将结果天数除以
30.0
以确保它不是 integer division。 - 四舍五入。这是您需要添加的 30 天区块数。
- 乘以 30 得到天数。
这不能很好地转换为 non-day 间隔,例如月或年。例如,这个:
DATEADD(month, 6 * CEILING(( IIF(CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME), 1, 0) + DATEDIFF(month, CA1.ReviewDueDate, getdate()) ) / 6.0), CA1.ReviewDueDate);
将是错误的,因为如果今天的日期在同一个月并且 CA1.ReviewDueDate
s 的时间不大于今天的时间,那么 return CA1.ReviewDueDate
未修改天。
所以除了 months/years:
你还需要调整天数的差异DATEADD(
month,
6 * CEILING( (IIF( (day(getdate()) > day(CA1.ReviewDueDate) or CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME)), 1, 0) + DATEDIFF(month, CA1.ReviewDueDate, getdate())) / 6.0 ),
CA1.ReviewDueDate
)
DATEADD(
year,
1 * CEILING( (IIF( (month(getdate()) > month(CA1.ReviewDueDate) or day(getdate()) > day(CA1.ReviewDueDate) or CAST(getdate() AS TIME) > CAST(CA1.ReviewDueDate AS TIME)), 1, 0) + DATEDIFF(year, CA1.ReviewDueDate, getdate())) / 1.0 ),
CA1.ReviewDueDate
)
所有这些都严格假设 CA1.ReviewDueDate
总是小于 getdate()
。如果不是,您想将整个事情包装到另一个处理这种情况的 case when ... end
中,并在今天已经过去时做一些不同的事情。