在SQL中将一个运算的结果乘以运算n次?

Multiply the result of an operation by the operation n times in SQL?

我正在尝试在 SQL 中实现一种基于流逝时间的衰减机制。因此,随着时间的推移,该项目 "decays" 会更快(基于之前的产品)。

这是通过具有 "Decay" 值、生成日期和周期性(即衰减值应用之间的时间量)来实现的。

所以如果一个项目有 25% 的衰减,从 1 开始,生成日期是今天和 3.5 分钟前,它已经衰减了 3 倍,导致 'weighted value':

1m - 1.25

2m - 1.5625

3m - 1.953125

等等

s * ((1+d) ^ n)
where
s = starting value
d = decay % as decimal
n = number of elapsed periods

相关的 SQL 是:

ORDER BY

    1.00 * POWER((1.00+[Decay]),CONVERT(float, DATEDIFF(minute,[GenerationDate],GETUTCDATE())))

但是这会导致算术溢出,所以现在我必须在 WHERE 语句中确定一些内容,以阻止我按太旧且会导致溢出的项目进行排序,或者至少将其最大化到最大值小数点。

试试这个

SET ARITHABORT OFF;
SET ARITHIGNORE ON;
SET ANSI_WARNINGS OFF;

这不会挂起溢出错误,而是 return null

最后编辑 Null

select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate

假设 s > 0d > 0,那么您可以利用这样一个事实,即实数的有序集 X 在变换 Y = Log(X) 下保留了它的顺序.取你函数的 Log,你会得到一个符合 IEEE 浮点数的实数:

X = s * ((1+d) ^ n)
Log(X) = Log(s * ((1 + d) ^ n)))
Log(X) = Log(s) + Log((1 + d) ^ n)
Log(X) = Log(s) + n * Log(1 + d)

然后,利用 Log(s) 是常数项这一事实,您可以简化为以下 ORDER BY

ORDER BY
    CONVERT(float, DATEDIFF(minute, [GenerationDate], GETUTCDATE())) * Log(1.00+[Decay])

请注意,您将忽略在此 table 上定义的 任何 索引,因为您是通过计算操作进行排序的。如果这是您希望经常执行的操作,请考虑添加一个带有上述表达式索引的计算列或您执行(例如)每小时更新的静态列。