【性能优化】5.5 [有序遍历] 前半序分组
5.5 前半序分组
还是以帐户、日期的帐户交易表,现在我们想把它换一种次序,将帐户内的交易记录改成按发生日的星期几排序,即把所有周日的交易都排到一起、然后再排周一的、周二、…。这本质上是把原表换了一个排序方式,而这是一个大排序,使用大排序算法就需要产生缓存文件,性能不会好。
不过, 我们发现原数据表已经按帐户有序,可以说是有“半有序”的,而在每个(有序的)帐户内还无序的数据量并不大。这时候,我们可以使用上面讲的程序游标来做这个大排序。
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) 排序。