说明:With在天软中有两处功能,一是设置系统参数,二是优化表联接运算,其具体应用请看下文描述。
1、对语句段临时系统参数变量的设置
语法一:with *, SysParamArray Do begin 语句段 end;
说明:在with之前的系统参数变量基础上按SysParamArray重新设置系统参数(没有重新设置的系统参数保持不变),结束后恢复到with之前的状态。
范例1:
Endt:=20190814T;
setsysparam(pn_cycle(),cy_day());
setsysparam(pn_stock(),'SZ000002');
setsysparam(pn_date(),Endt);
//万科A在20190814日的当日收盘价与成交量
c:=close();
v:=vol();
A:=array(pn_cycle():cy_1m(),pn_date():Endt+14.5/24);
with *,A do
begin // 万科A在2019-08-14 14:30:00时的分钟线收盘价与成交量
c1:=close();
v1:=vol();
end;
return array('日线':('收盘价':c,'成交量':v),
'分钟线(14:30)':('收盘价':c1,'成交量':v1));
//返回
| 收盘价 | 成交量
|
---|
日线 | 27.13 | 52847504
|
分钟线(14:30) | 27.05 | 43600 |
语法二:with **, SysParamArray Do begin 语句段 end;
说明:直接切换为SysParamArray的系统参数环境,with前原有的系统参数全部失效(没有重新设置的系统参数值全为nil),结束后恢复到with之前的状态。
范例2:若将范例1中的with *,A do更改为with **,A do会报运行时错误,原因是没有设置股票代码。正确的用法如下:
Endt:=20190814T;
setsysparam(pn_cycle(),cy_day());
setsysparam(pn_stock(),'SZ000002');
setsysparam(pn_date(),Endt);
//万科A在20190814日的当日收盘价与成交量
c:=close();
v:=vol();
A:=array(pn_stock():'SH600000',pn_cycle():cy_1m(),pn_date():Endt+14.5/24);
with **,A do
begin // 浦发银行在2019-08-14 14:30:00时的分钟线收盘价与成交量
c1:=close();
v1:=vol();
end;
return array('日线(万科A)':('收盘价':c,'成交量':v),
'分钟线(14:30,浦发银行)':('收盘价':c1,'成交量':v1));
//返回
| 收盘价 | 成交量
|
---|
日线(万科A) | 27.13 | 52847504
|
分钟线(14:30,浦发银行) | 11.3 | 97500 |
语法三:with [S=>StockID,T=>Time] Do begin 语句段 end;
说明:在with之前的系统参数变量的基础上,变更当前股票(S)或当前时间(T)的系统参数值,结束后恢复到with之前的状态。该方法目前只支持变更股票与时间。
范例3:
setsysparam(pn_cycle(),cy_day());
setsysparam(pn_stock(),'SZ000002');
setsysparam(pn_date(),20190814T);
re:=array();
//万科A在20190814日的当日收盘价与成交量
re[0]:=array('StockID':DefaultStockID(),'Date':sp_time(),'close':close(),'vol':vol());
//浦发银行在20190814日的当日收盘价与成交量
with s=>'SH600000' do
begin re[1]:=array('StockID':DefaultStockID(),'Date':sp_time(),'close':close(),'vol':vol());
end
// 浦发银行在20190813日的当日收盘价与成交量
with s=>'SH600000',t=>20190813T do //只有一条语句,可以省掉begin...end
re[2]:=array('StockID':DefaultStockID(),'Date':sp_time(),'close':close(),'vol':vol());
return re;
//注:其中DefaultStockID()为获取当前股票,sp_time()为获取当前交易日
//返回
StockID | Date | close | vol
|
---|
SZ000002 | 43691 | 27.13 | 52847504
|
SH600000 | 43691 | 11.28 | 19874457
|
SH600000 | 43690 | 11.33 | 18839979 |
语法四:R[i]:=#函数名(参数…) with array(系统参数列表…);
说明:在网格计算中,with 的作用就是将节点环境设置为“array(系统参数列表…)”。 如果函数在节点内与系统参数无关,则不需要 with。网格计算具体请参考:FAQ:
Q:天软网格计算默认开通的并行数是多少?如何设置网格计算?
范例4:
Function NoName38();
Begin
s:='SZ000002';
t:=array();
t['date']:=Markettradedayqk(20190801T,20190815T);
t:=`t;
for i:=0 to length(t)-1 do
t[i,'close']:=#getclose() with array(pn_stock():s,pn_date():t[i,'date']);
return t;
End;
Function getclose();
begin
return close();
end
范例5:网格中指定服务器群进行计算,相关说明可参考:FAQ:
Q:在网格中如何指定服务器进行运算
Function NoName37();
Begin
s:=%%g 192.168.102.13:z:\se%%g;
A:=array();
stocks:=getbk('上证50');
for i:=0 to length(stocks)-1 do
begin
A[i]:=#testwith() with array("@AppServerId@":s,pn_stock():stocks[i]);
end
return A;
End;
function testwith();
begin
echo TSAppserver();
return array('StockID':DefaultStockID(),'zf':stockzf4(20190815T));
end
//打印信息如下所示(没有展示所有打印结果):
192.168.102.13:9072:6952(z:\server\bin\)
192.168.102.13:9072:11984(z:\server\bin\)
192.168.102.13:9072:4728(z:\server\bin\)
192.168.102.13:9072:5704(z:\server\bin\)
192.168.102.13:9072:11752(z:\server\bin\)
2、对表联接的优化支持
语法:with(等式左表达式组 on 等式右表达式组)
其中,左右表达式组中的多个表达式用逗号“,”分隔。
说明:该用法是对join on的一个优化,with on可以把笛卡尔积的计算复杂度降低到线性复杂度(参与运算的两个表的大小之和)。
特别说明:with on会利用两组表达式进行预运算,并建立快速索引,解决效率问题,一般来说With On的计算复杂度和N+M是一个量级,而ON条件的计算复杂度和N*M是一个量级(假定左右输入的数据集合的记录数分别为N和M),在N和M比较大的时候,性能的差异可以体现得非常明显,达到几个数量级的差异。
范例6:单字段表联接
Table1 := Array(
('A':1,'B':2,'C':7),
('A':10,'B':3,'C':12),
('A':4,'B':20,'C':34) );
Table2 := Array(
('D':3,'E':10,'A':5),
('D':56,'E':72,'A':4),
('D':78,'E':28,'A':10) ) ;
return Select *,[1].['A'] from Table1 left join Table2 WITH ([1].['A'] ON [2].['A']) end;
//返回
A | B | C | D | E
|
---|
1 | 2 | 7 | |
|
10 | 3 | 12 | 78 | 28
|
4 | 20 | 34 | 56 | 72 |
范例7:多字段表联接
Table1 := Array(
('A':1,'B':2,'C':7),
('A':10,'B':3,'C':12),
('A':4,'B':20,'C':34) );
Table2 := Array(
('D':3,'B':2,'A':1),
('D':56,'B':72,'A':4),
('D':78,'B':28,'A':10) );
return Select [1].*,[2].['A'] as 'A2',[2].['B'] as 'B2',[2].['D'] from Table1 full join Table2
WITH ([1].['A'],[1].['B'] ON [2].['A'],[2].['B']) end;
//注:表联接时,同名列会被后面的列值覆盖,如需保留建议更字段名
//返回
A | B | C | A2 | B2 | D
|
---|
1 | 2 | 7 | 1 | 2 | 3
|
10 | 3 | 12 | | |
|
4 | 20 | 34 | | |
|
| | | 4 | 72 | 56
|
| | | 10 | 28 | 78 |
范例8:join with on与普通join on的效率测试对比
A:=select * from infotable 328 of 'OF000001' end; //4284
C:=select * from infotable 322 of 'OF000001' end; //20
mtic;
D:=select * from A join C on [1].['截止日']=[2].['截止日'] end;
echo '普通联接:',mtoc;
mtic;
G:=select * from A join C with([1].['截止日'] on [2].['截止日']) end;
echo 'with on联接:',mtoc;
return D=G;
//打印结果
普通联接:0.105497
with on联接:0.00225725