在SQL中,聚合函数sum(x),avg(x),max(x),min(x) 当x为空或仅包含NULL值时,将返回NULL。
在KDB中,sum和avg返回零,而max和min返回(+或 - )无穷大。
为了获得返回null的所需行为,我提出了两个选项:
(A)删除空值,并在正常聚合之前检查结果是否为空
nsum:{[x] x: x where not null x; $[0=count x; 0N; sum x]}
(B)创建一个新的聚合,在累积
之前检查每个项目是否为null
请注意,我们仍然需要检查一个空列表。
nsum:{[z] $[0=count z; 0N; {[x;y] $[null x; y; null y; x; x+y]}/ z ]}
是否有比A或B更好(更快和/或更方便)的方式?
方法(B)是否比方法(A)更好地执行?
方法(A)具有为任何聚合函数工作的优点。 方法(B)不适用于"平均",因为没有成对函数 这将产生一个运行平均值(需要知道已经应用了多少项)。
相关问题:检查空列表的速度是否比0=count x
更快,例如0= type first x
?
谢谢!
答案 0 :(得分:2)
您可以使用all运算符。您也可以(可能应该)根据列表的类型返回null。
f:{$[all null x;(neg type x)$"";sum x]}
q)f `int$()
0N
q)f 0n 0n 0n 0n
0n
要衡量效果,请使用\t
(计时器)或\ts
(时间和空格)。 http://code.kx.com/q/ref/syscmds/#t-timer
f1:{$[all null x;(neg type x)$"";sum x]}
fa:nsum:{[x] x: x where not null x; $[0=count x; 0N; sum x]}
fb:{[z] $[0=count z; 0N; {[x;y] $[null x; y; null y; x; x+y]}/[z] ]}
allnull:1000000#0N
withnull:10000000?(1000#0N,til 10)
withoutnull:10000000?10
\ts do[10;f withnull]
612 16777504
..
..
你会发现方法B(fb)是最慢的。 f1比fa更快(除了allnull列表情况,速度可比)并且使用更少的空间。
答案 1 :(得分:2)
对于min / max,你可以通过使用int / long列表添加和减去1来做一些诡计,以确保返回空值。这是最近在kxCon2016由Attila Vrabecz提到的。它是对“数字线”中出现null和无穷大的方式/操作的操纵。虽然它们不是很通用,但具体针对每个操作:
q)a:`int$()
q)b:1 2 3i
q)c:0N 0Ni
q)-1+max 1+a
0N
q)-1+max 1+b
3
q)-1+max 1+c
0N
q)1+min a-1
0N
q)1+min b-1
1
q)1+min c-1
0N