集算器支持有序集合、对象式访问、分步计算,可以简化复杂的SQL式计算。实际使用中有两种常见的应用结构:独立使用、JAVA集成。下面先举例说明独立使用的步骤。
表sales存储着多年的订单数据,要求根据表计算出指定时间段内各月份的销售额比上期。部分源数据如下:
步骤一:在集算器IDE中连接数据库
可以同时连接多个数据源进行混合计算,本案例使用mySQL数据库,JDBC配置如下:
步骤二:在集算器IDE中完成算法
先按时间段从数据库查询数据,begin和end是查询参数;再按年、月分组,并对Amount汇总;最后在A2基础上增加一个新的字段lrr(按月比上期),其中mAmount代表当期销售额,mAmount[-1]代表上期销售额。
步骤三:执行脚本
执行脚本后要求输入参数值,界面如下:
点“OK”后完成计算,点击相应的单元格可观察每一步的计算结果,比如A2是这样:
A3存储最终结果,如下:
注:上面是依次执行所有单元格,集算器还支持用快捷键执行当前格。
对于设计完成的脚本文件,可以通过命令行或批处理执行,而不必每次打开IDE运行。
命令行执行脚本
使用esprocx.exe可执行脚本,形如esprocx -R d:\Query1.dfx 2012-06-01 2014-06-30,-R选项可显示计算结果,默认显示最后一个单元格,如下:
详情请参考集算器集成与应用之命令行。
除了独立使用,有时还需要在JAVA中调用集算器的计算结果。
JAVA集成
JAVA主程序可以JDBC的方式调用集算器脚本,代码如下:
Class.forName(“com.esproc.jdbc.InternalDriver”);
con= DriverManager.getConnection(“jdbc:esproc:local://”);
//调用集算器脚本(类似存储过程),其中Query1是dfx的文件名
st =(com. esproc.jdbc.InternalCStatement)con.prepareCall(“call Query1 (?,?)”);
java.util.Date dateBegin = new SimpleDateFormat(“yyyy-MM-dd”).parse(“2010-01-01″);
java.sql.Date sqlDateBegin = new java.sql.Date(dateBegin.getTime());
java.util.Date dateEnd = new SimpleDateFormat(“yyyy-MM-dd”).parse(“2010-12-31″);
java.sql.Date sqlDateEnd = new java.sql.Date(dateEnd .getTime());
st.setDate(1, sqlDateBegin);
st.setDate(2, sqlDateEnd );
//执行脚本
st.execute();
//获取结果集
ResultSet rs = st.getResultSet();
……
集算器默认返回最后一个单元格,也可用result语句返回指定单元格。返回值是符合JDBC标准的ResultSet对象,调用集算器脚本和访问数据库的方法完全一样,熟悉JDBC的程序员可以很快掌握。
支持JDBC接口的报表工具也可以调用集算器脚本,详情请参考集算器辅助报表开发的集成方法。
上面说明了JAVA集成集算器的一般方法,下面说明几种特殊情况。
简单脚本无文件
集算器脚本比较简单时,可以将脚本直接写在JAVA中,而不必专门存储一个脚本文件。需要注意的是,prepareStatement里的参数占位符在SQL中是问号,但问号是集算器的保留符号,因此要用”arg1,arg2,arg3”的形式依次占位,代码如下:
ResultSet rs1 =(com. esproc.jdbc.InternalCStatement)con.prepareStatement(“$select * from sales3 where OrderDate>=? and OrderDate<=?;arg1,arg2\n =A1.groups(year(OrderDate):y,month(OrderDate):m;sum(Amount):mAmount)\n =A2.derive(mAmount/mAmount[-1]:lrr)");
java.util.Date dateBegin = new SimpleDateFormat(“yyyy-MM-dd”).parse(“2010-01-01″);
java.sql.Date sqlDateBegin = new java.sql.Date(dateBegin.getTime());
java.util.Date dateEnd = new SimpleDateFormat(“yyyy-MM-dd”).parse(“2010-12-31″);
java.sql.Date sqlDateEnd = new java.sql.Date(dateEnd .getTime());
st.setDate(1, sqlDateBegin);
st.setDate(2, sqlDateEnd );
st.execute();
写入另一个数据库
计算结果并非一定会返回,比如将A3更新到oracle数据库,代码如下:
myDB1和orDB1是不同的数据源,函数update可将序表A3更新到orDB1的summaryTable表,其中字段Year、Month对应A3中的y、m,字段mAmount、lrr在A3中有同名字段。
相应的,JAVA集成代码不必用st.getResultSet()获取结果。
大返回值
有时候计算结果会超出内存,这时就要用集算器游标函数返回结果,相应的JAVA代码要用JDBC流来访问。比如:tb1是mySQL库中的大表,tb2是Oracle库中的大表,两者结构相同但数据有差异,现在要找到ID相同的记录。
集算器代码如下:
函数cursor可执行SQL并返回游标,函数merge可进行有序数据的归并,@x表示对游标归并,@i表示归并的结果为交集。
A2的计算结果也是游标,JAVA主程序无法一次性读入内存,应当分批次读,代码如下;
st =(com. esproc.jdbc.InternalCStatement)con.prepareCall(“call bigMerge ()”);
st.setFetchSize(1000);//设置每批次读取的记录数。
st.execute();
ResultSet rs = st.getResultSet();
while (rs.next()) {
……
}