在SQL中将操作的结果乘以n次操作n次?

时间:2016-03-14 20:15:30

标签: sql sql-server math logic

我正在尝试在SQL中实现一个基于已经过去的时间量的衰减机制。因此,随着时间的推移,该项目“衰减”得更快(基于之前的产品)。

这是通过具有“衰减”值,生成日期和周期性来实现的,即应用衰减值之间的时间量。

因此,如果一个项目的衰减为25%,从1开始,具有今天和3.5分钟前的生成日期,它将已经衰减3x,从而产生“加权值”:

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语句中确定某些东西会阻止我按太旧的项目排序并导致溢出,或者至少将其最大化为a的最大值小数。

2 个答案:

答案 0 :(得分:2)

假设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])

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

答案 1 :(得分:1)

试试这个

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

这不会挂起溢出错误但会返回null

编辑为最后

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