Java使用jdbc连接Hive比较简单,但是Hive的计算能力相对于其它数据库的SQL而言较弱,要完成非常规的计算需要将数据取出后用Java进一步计算,编程比较麻烦。
使用集算器配合Java编程,可以减少Java使用Hive时要进行复杂计算工作量。下面我们通过例子来看一下具体作法:Hive中的orders表中保存了订单的明细数据,需要计算同期比和比上期。数据如下:
ORDERID CLIENT SELLERID AMOUNT ORDERDATE
1 UJRNP 17 392 2008/11/2 15:28
2 SJCH 6 4802 2008/11/9 15:28
3 UJRNP 16 13500 2008/11/5 15:28
4 PWQ 9 26100 2008/11/8 15:28
5 PWQ 11 4410 2008/11/12 15:28
6 HANAR 18 6174 2008/11/7 15:28
7 EGU 2 17800 2008/11/6 15:28
8 VILJX 7 2156 2008/11/9 15:28
9 JAYB 14 17400 2008/11/12 15:28
10 JAXE 19 19200 2008/11/12 15:28
11 SJCH 7 13700 2008/11/10 15:28
12 QUICK 11 21200 2008/11/13 15:28
13 HL 12 21400 2008/11/21 15:28
14 JAYB 1 7644 2008/11/16 15:28
15 MIP 16 3234 2008/11/19 15:28
…
比上期是指用当期数据和上期数据进行比较,以月作为时间间隔,比如用4月份的销售额除以3月份的销售额,这称为4月份的比上期。同期比是指用当期数据和上一周期的同期数据进行比较,比如2014年4月份的销售额除以2013年4月份的销售额。因为Hive没有窗口函数,所以难以完成这个计算需求,必须编写嵌套的SQL子查询,而Hive对子查询的支持也不够完备,这个计算目标经常需要放在外部实现。集算器esProc则可以比较容易的实现,具体代码如下:
A1:使用定义好的Hive数据源,通过jdbc连接数据库。
A2:按时间段从数据库查询数据,begin和end是外部参数,比如begin=”2011-01-01 00:00:00″,end=”2014-07-08 00:00:00″(即当天日期,可用now()函数获取)。
A3:对订单按照年份和月份进行分组,并汇总求得每月的销售额。
A4:增加一个新的字段lrr,即按月比上期,其表达式为mAmount/mAmount[-1]。代码中mAmount代表当期销售额,mAmount[-1]代表上期销售额。需要注意的是,初始月份的比上期值为空(即2011年1月)。
A5:将A4按照月、年排序,以便计算同期比。完整的代码应当是:=A4.sort(m,y),由于A4本来就是按年排序的,因此只需按月排序就可以达到目的,即A4.sort(m),这样性能也高。A6: 增加一个新的字段yoy,即月销售额的同期比,其表达式为if(m==m[-1],mAmount/mAmount[-1],null),这表示月份相同时才进行同期比计算。需要注意的是,初始年份(即2011年)各月份的同期比为空。
A7:将A6按照年逆序月正序进行排序。需要注意的是,数据只到2014年7月为止。结果如下:
A8:关闭Hive数据库连接。
A9:返回结果。
在Java程序中使用esProc JDBC调用这段程序获得结果的代码如下:(将上述esProc程序保存为test.dfx):
//建立esProc jdbc连接
Class.forName(“com.esproc.jdbc.InternalDriver”);
con= DriverManager.getConnection(“jdbc:esproc:local://”);
//调用esProc 程序(存储过程),其中test是dfx的文件名
st =(com.esproc.jdbc.InternalCStatement)con.prepareCall(“call test(?,?)”);
//设置参数
st.setObject(1,”2011-01-01 00:00:00″);//begin
st.setObject(1,”2014-07-08 00:00:00″);//end
//执行esProc存储过程
st.execute();
//获取结果集
ResultSet set = st.getResultSet();
集算器访问Hive和访问普通数据库一样,配好Hive的JDBC即可,这里不再赘述。