【性能优化】5.4 [有序遍历] 前半序分组

 

【性能优化】5.3 [有序遍历] 程序游标

5.4 前半序分组

还是以帐户、日期的帐户交易表,现在我们想把它换一种次序,将帐户内的交易记录改成按发生日的星期几排序,即把所有周日的交易都排到一起、然后再排周一的、周二、…。这本质上是把原表换了一个排序方式,而这是一个大排序,使用大排序算法就需要产生缓存文件,性能不会好。

不过, 我们发现原数据表已经按帐户有序,可以说是有“半有序”的,而在每个(有序的)帐户内还无序的数据量并不大。这时候,我们可以使用上面讲的程序游标来做这个大排序。


A

B

C

1

func

=file("trades.btx").cursor@b()

2


for B1;id

return B2.sort(day@w(dt))

3

return   cursor@c(A1)

取出每个帐户的数据后只做“后半”的排序,程序游标就能把结果收集起来返回期望的大排序结果。

当然,这种办法也可以用来做分组,比如要计算每个帐户每个星期几的交易总额,只要把上面的 A3 改成

return cursor@c(A1).group(id,day@w(dt);sum(amount))

也可以在子程序里处理,这样返回数据量更少一点:



A

B

C

1

func

=file("trades.btx").cursor@b()

2


for B1;id

return B2.groups(id,day@w(dt);sum(amount))

3

return cursor@c(A1)

这种情况在现实中并不罕见,SPL 直接在 group 函数上提供了一个选项来处理:


A

1

=file("trades.btx").cursor@b()

2

=A1.group@q(id;day@w(dt);sum(amount))

注意 group@q 有三组参数,第一组表示已经先有序的分组键,第二组是还没有序的分组键,第三组是汇总表达式。再加个 @q 选项,SPL 就知道先利用有序游标取出 id 相同的部分再按 day@w(dt) 去分组了。

它也可以直接用来排序:


A

1

=file("trades.btx").cursor@b()

2

=A1.group@qs(id;day@w(dt))

再加 @s 选项表示不做分组只做排序,即在 id 相同的数据中按 day@w(dt) 排序。

【性能优化】5.5 [有序遍历] 后半序分组

【性能优化】 前言及目录