我正在尝试在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的最大值小数。
答案 0 :(得分:2)
假设s > 0
和d > 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