在游标的使用方法中,前面一再强调过游标是单次遍历的。在7.2.3用游标执行计算 中,我们了解了用游标执行计算,生成新的游标的方法。但是,即使是在这样的使用中,游标仍然只能执行一次遍历计算,只有最终生成的游标中的cs.fetch() 函数能够有效取得数据。遍历结束后,计算过程中产生的其它游标均不能再次读取数据。
有时,在一次读取数据的过程中,我们需要同时计算多个数据,此时可以使用管道。管道与游标类似,可以用channel() 函数新建管道,并用cs.push(ch) 函数将管道添加到游标cs,或者用ch2.push(ch) 函数将管道添加到另一个管道ch2中。管道在新建时只会存储所需计算的动作,只有在游标中实际执行fetch动作取数时才会自动执行计算并记录结果。管道可以执行多种计算,支持的函数与游标类似,如ch.select(), ch.new(), ch.derive(), ch.(), ch.news(), ch.run(), ch.switch(), ch.join(), ch.conj(), ch.group()等。在管道中,可以定义各种结果集,如用ch.fetch() 定义返回管道中的所有数据,用ch.id() 定义返回去重计算的结果,用ch.sortx() 定义返回排序后的结果,或者用ch.groupx() 和ch.groups() 定义返回分组统计的结果等。管道定义了结果集后,可以用ch.result() 函数获取管道中计算的结果。如:
|
A |
B |
C |
D |
1 |
=file("Order_Wines.txt") |
|
|
|
2 |
=A1.cursor@t() |
|
|
|
3 |
=channel() |
>A3.select(SalesID==1) |
>A3.fetch() |
>A2.push(A3) |
4 |
=A2.select(month(Date)==8) |
|
|
|
5 |
=channel() |
>A4.push(A5) |
>A5.select(SalesID==1) |
>A5.fetch() |
6 |
=A4.fetch() |
=A3.result() |
=A5.result() |
|
当A6中执行fetch时,游标中的数据被读取出来,管道中的计算也随之完成,这样就可以通过定义管道计算,在一次遍历游标数据的过程中,得到多个计算结果。执行后,A6,B6,C6中的结果如下:
A3和A5中新建了管道,两个管道中执行的计算是类似的,都是选出SalesID为1的记录。但是可以发现B6和C6中的结果是不同的,这是由于A3管道添加到了A2的游标中,A2读取所有销售记录;而A5管道添加到了A4的游标中, A4中的游标添加了计算,只读取8月份的销售数据。
另外,考察第3行与第5行的代码可以发现,在执行push后,管道中仍然可以执行有效的计算。但是,如果已经用ch.fetch(), ch.id() 等函数定义了管道返回的结果,就不能在管道中继续执行计算了。
除了用ch.fetch() 获取全部数据,在管道中还可以使用排序、分组汇总等计算,如:
|
A |
B |
C |
D |
1 |
=file("Order_Wines.txt") |
|
|
|
2 |
=A1.cursor@t() |
|
|
|
3 |
=channel() |
>A3.select(SalesID==1) |
>A2.push(A3) |
|
4 |
=channel() |
>A4.sortx(Amount) |
>A3.push(A4) |
>A3.groups(month(Date); count(~):Count) |
5 |
=A2.skip () |
=A3.result() |
=A4.result() |
=C5.fetch() |
在这里,A4中的管道添加到了A3的管道中,因此A4管道中的计算会在条件SalesID==1筛选过的记录中执行。A3中定义结果集的groups函数要在最后,因此要放到C4中的push后执行。管道函数ch.sortx() 和ch.groupx() 等定义的结果集,返回的结果会是游标,需要fetch后才能获得结果,如D5中的处理。另外,虽然A5中执行的是游标的skip操作,这同样也会使游标中的数据流过管道,获得统计结果。计算后,B5, D5中的结果如下:
在管道中附加计算时,除了使用集算器提供的如ch.select(), ch.new() 等函数外,还可以用ch.attach(x) 设定的表达式x来附加计算,表达式中,用~表示管道中前面的计算已经处理过的数据。如:
|
|
B |
C |
1 |
=file("Order_Wines.txt") |
|
|
2 |
=A1.cursor@t() |
|
|
3 |
=channel() |
>A3.select(SalesID==1) |
>A2.push(A3) |
4 |
|
>A3.attach(~.(~.array())) |
>A3.fetch() |
5 |
=A2.skip () |
=A3.result() |
|
在B3中,在管道A3中附加计算,筛选SalesID为1的销售记录,在B4中,用函数继续附加计算,将每条记录都转换为序列。执行后,B5中的结果如下: