gbe*_*ger 3 sql logarithm histogram
我的表:
val
1
2
3
4
5
6
10
15
Run Code Online (Sandbox Code Playgroud)
预期结果:
bin | qty
1 | 1
2 | 2
4 | 3
8 | 3
Run Code Online (Sandbox Code Playgroud)
这意味着有包含/不包含范围,
在这种情况下,您的 bin 大小(以对数形式表示)为 2。
如果您希望使用其他 bin 大小,请替换以下脚本中的 2s。
select
pow(2, floor(ln(val) / ln(2))) as bin,
count(bin) as qty
from
mytable
group by
bin;
Run Code Online (Sandbox Code Playgroud)
首先,我们以 2 为基数记录您的值。log(val, 2)可能在某些 RDBMS 中工作,但如果不是,请记住log(val, 2) = ln(val) / ln(2).
val | ln(val) / ln(2)
1 | 0
2 | 1
3 | 1.58496250072
4 | 2
5 | 2.32192809489
Run Code Online (Sandbox Code Playgroud)
然后我们把这个:
val | floor(ln(val) / ln(2))
1 | 0
2 | 1
3 | 1
4 | 2
5 | 2
Run Code Online (Sandbox Code Playgroud)
最后,我们使用 2 的幂将这些下限值转换为对数 bin 值。
val | pow(2, floor(ln(val) / ln(2)))
1 | 1
2 | 2
3 | 2
4 | 4
5 | 4
Run Code Online (Sandbox Code Playgroud)
其余的只是按对数箱和计数进行分组。
如果您的 RDBMS 不支持pow(x, y),您可以使用exp(y * ln(x)). 然后表达式变为:
exp(floor(ln(val) / ln(2)) * ln(2))
Run Code Online (Sandbox Code Playgroud)
log(0) 未定义。在我测试的 RDBMS 中,它返回 null。
如果您的表的值为 0,您很可能希望将它们放在 0 和 1 之间。为此,您可以使用 ifnull(..., 0) 包装整个表达式,如下所示:
ifnull(pow(2, floor(ln(val) / ln(2))), 0)
Run Code Online (Sandbox Code Playgroud)
负数的对数未定义...但您可能希望将它们分类为 [0 到 -1)、[-1 到 -2)、[-2 到 -4)、[-4 到 -8) 等” .
如果您的数据库具有负值,您可以通过首先abs在您的值中使用来实现该分箱,然后最后通过将结果乘以 来恢复其原始信号val/abs(val)。然后你的表达变成:
pow(2, floor(ln(abs(val)) / ln(2))) * val/abs(val)
Run Code Online (Sandbox Code Playgroud)
如果您的数据库同时具有负值和零值,则应将ifnull其他所有内容都包装起来。否则,该val/abs(val)部分会使您除以零,重新引入空值。
ifnull(pow(2, floor(ln(abs(val)) / ln(2))) * val/abs(val), 0)
Run Code Online (Sandbox Code Playgroud)