我有一个标量函数,正在转换为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()
时,需要将30天添加到@ReviewDate
中。
当我尝试理解转换后的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循环是如何转换的,因此我在与另外两个进行斗争。
感谢您对首次转换的任何帮助。
如果有人可以帮助转换其他两个,那也将有所帮助。
答案 0 :(得分:1)
您本身不需要cross apply
。显然,它只是用来从多个位置引用计算出的表达式。
cross apply
中的公式直接计算需要添加到@ReviewDueDate
的30天块中的多少,以便超过getdate()
:
@ReviewDueDate
与今天之间的天差。@ReviewDueDate
的一天中的时间大于今天的一天中的时间,请添加一天。30.0
,以确保它不是integer division。这不能很好地转换为非天间隔,例如几个月或几年。例如,这:
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
的日期时间不大于今天的时间,它将返回未修改的CA1.ReviewDueDate
。
因此,您需要调整除月/年之外的天数差异:
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
中来处理这种情况,并在今天已经过去时执行其他操作。