FAQ > 金融建模 > 建模问题 > 语法相关

Q:with的使用说明    

  • 说明: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.1352847504
    分钟线(14:30)27.0543600


    语法二: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.1352847504
    分钟线(14:30,浦发银行)11.397500


    语法三: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()为获取当前交易日
    //返回
    StockIDDateclosevol
    SZ0000024369127.1352847504
    SH6000004369111.2819874457
    SH6000004369011.3318839979


    语法四: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;
    //返回
    ABCDE
    127
    103127828
    420345672


    范例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;
    //注:表联接时,同名列会被后面的列值覆盖,如需保留建议更字段名
    //返回
    ABCA2B2D
    127123
    10312
    42034
    47256
    102878


    范例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