2016-10-01 31 views
3

在SQL中,當x爲空或僅包含NULL值時,聚合函數sum(x),avg(x),max(x),min(x) 將返回NULL。獲取聚合函數以在KDB中返回null

在KDB中,sum和avg返回零,而max和min返回(+或 - )無窮大。

要得到返回null期望的行爲我想出了2種選擇:

(A)卸下空值,並檢查如果結果是空的聚集和往常一樣

nsum:{[x] x: x where not null x; $[0=count x; 0N; sum x]} 

之前( B)創建一個新的聚合,在累積之前檢查每個項目是否爲空
請注意,我們仍然需要檢查空白列表。

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

謝謝!

回答

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列表的情況,速度是可比的)並且使用較少的空間。

2

對於最小/最大,你可以做一些欺騙性的加/減1的int/long列表來確保返回空值。這是最近在Attila Vrabecz在kxCon2016上提到的。這是對「數字線」上出現空白和無限的方式/操作的操縱。雖然它們並不是很一般,但是對於每個操作都是特定的:

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