Inceptor支持用户自定义函数,本节将首先举例说明如何自定义函数并应用在Inceptor里,之后将列举Inceptor自增的UDF
自定义UDF时需要注意以下几点:
1.自定义UDF需要继承org.apache.hadoop.hive.ql.exec.UDF
2.需要实现evaluate函数
3.evaluate函数支持重载
以下代码实现了两个数求和的UDF,evaluate函数代表两个整型数据相加或两个浮点型数据相加
package inceptor.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
public final class Add extends UDF {
public Integer evaluate(Integer a, Integer b) {
if (null == a || null == b) {
return null;
}
return a + b;
}
public Double evaluate(Double a, Double b) {
if (a == null || b == null)
return null;
return a + b;
}
}
实际使用时,需要执行以下几步:
1.程序打包放到目标机器上进入Inceptor客户端,添加jar包:add jar [jar_file_path];
2.创建临时函数:CREATE TEMPORARY FUNCTION my_add AS 'inceptor.udf.Add';
3.使用临时函数:SELECT my_add(scores.math, scores.art) FROM scores;
4.使用完成后销毁临时函数:DROP TEMPORARY FUNCTION my_add;
自定义UDAF时需要注意以下几点:
1.自定义UDAF需要继承org.apache.hadoop.hive.ql.exec.UDAF
2.内部类Evaluator需要实现UDAFEvaluator接口:Evaluator需要实现init、iterate、terminatePartial、merge、terminate这几个函数
2.1.init函数实现接口UDAFEvaluator的init函数
2.2.iterate接收传入的参数,并进行内部的轮转,其返回类型为boolean
2.3.terminatePartial无参数,其为iterate函数轮转结束后,返回轮转数据,terminatePartial类似于hadoop的Combiner
2.4.merge接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean
2.5.terminate返回最终的聚集函数结果
以下代码实现了一个求平均数的UDAF
package inceptor.udaf;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
public class Avg extends UDAF {
public static class AvgState {
private long mCount;
private double mSum;
}
public static class AvgEvaluator implements UDAFEvaluator {
AvgState state;
public AvgEvaluator() {
super();
state = new AvgState();
init();
}
public void init() {
state.mSum = 0;
state.mCount = 0;
}
public boolean iterate(Double o) {
if (o != null) {
state.mSum += o;
state.mCount++;
}
return true;
}
public AvgState terminatePartial() {
return state.mCount == 0 ? null : state;
}
public boolean merge(AvgState o) {
if (o != null) {
state.mCount += o.mCount;
state.mSum += o.mSum;
}
return true;
}
public Double terminate() {
return state.mCount == 0 ? null : Double.valueOf(state.mSum
/ state.mCount);
}
}
}
实际使用时,需要执行以下几步:
1.程序打包放到目标机器上进入Inceptor客户端,添加jar包:add jar [jar_file_path];
2.创建临时函数:CREATE TEMPORARY FUNCTION my_avg AS 'inceptor.udaf.Avg';
3.使用临时函数:SELECT scores.art, my_avg(scores.math) FROM scores GROUP BY scores.art;
4.使用完成后销毁临时函数:DROP TEMPORARY FUNCTION my_avg;
下面列举Inceptor自增的UDF
trunc(date, format):支持string类型的date字段按format返回特定的日期string
trunc(number,num_digits):支持数字类型的按给定数值进行裁剪
to_char(date, pattern):把yyyy-MM-dd HH:mm:ss形式的string转化为输入pattern形式的string
to_char(datetime, pattern):把yyyy-MM-dd形式的string转化为输入pattern形式的string
to_char(number [,format]):把数值转化为string,基本类型(byte, short, int, bigint, float, double)转string或按照一定format转string
translate('input_string','from_string','to_string')
translate方法作用于input string(第一个参数)的字符上,规则为出现在from_string中的字符用to_string中对应位置的字符来替换。如果to_string的长度比from_string短,那么from_string中多出来的位置的字符会在output中被移除。
translate('abcdef', 'adc', '19'):返回 '1b9ef','1'代替'a','9'代替'd','c'被移除。
nvl(eExpr1, eExpr2):eExpr1为空时设为eExpr2的值,仅支持基本类型(包括string)
nvl2(eExpr1, eExpr2, eExpr3):eExpr1不为空时设置为eExpr2的值,为空时设置为eExpr3的值,仅支持基本类型(包括string)
dense_rank(hash_key, order_by_col1, order_by_col2 ...):dense_rank与rank的区别是dense_rank的排序号会持续+1递增的,不会由于部分字段相同排序号而跳跃,即按照1、2、2、2、3、4、5排序
select key1,key2,value,dense_rank(1,value) as rank from (select key1,key2,value from test_table distribute by hash(key1) sort by key1,key2,value) t;
greatest(value1, value2, value3, ....):字段属性必须为PRIMITIVE,且需要是相同的TypeInfo,或者能转成CommonBase
select key1,key2,value,group_max(key1,key2) as rank from (select key1,key2,value from test_table sort by key1) t;
NOTE:按照key1 group by之后对key2取其中的最大值,此方法不属于聚合函数,所以是逐行处理的。由于每个group内当前行记录只是基于其之前所有行的统计结果(而不是扫描group内所有行),所以每个group内前面部分行记录的最大值可能不是group真正的最大值:
1 12 string1 12
1 2 string1 12
1 11 string1 12
1 12 string2 12
2 NULL string1 12
2 -21 string1 -21
2 23 string1 23
2 4 string2 23
2 14 string2 23
3 32 string2 32
3 6 null 32
4 8 8
4 42 string2 42
5 54 string2 54
5 52 string1 54
5 NULL value5 54
6 12 502 12
6 64 string2 64
类似的函数还有group_min和group_sum
instr(str, substr):查找子字符串index
lag(hash_key,column[,offset[,default]]):用法和group_max等类似依赖于sort_by。此函数和oracle原生语法相同,取出当前行前面第N行的数据,其不支持取出后N行数据,暂时也没有其他类似方法提供该功能
注意事项如下:
1.column与default值需要是同一字段类型
2.offset只能为自然数,其默认值为1,即取前一行的字段数据,如果没有则为NULL,如果设为负数将全为NULL
范例:
select key1,key2,value,lag(key1,key2) as rank from (select key1,key2,value from test_table distribute by key1 sort by key1,value) t
1 11 string1 NULL
1 2 string1 11
1 12 string1 2
1 12 string2 12
2 NULL string1 NULL
2 -21 string1 NULL
2 23 string1 -21
2 14 string2 23
2 4 string2 14
3 6 null NULL
3 32 string2 6
4 8 NULL
4 42 string2 8
5 52 string1 NULL
5 54 string2 52
5 NULL value5 54
6 12 502 NULL
6 64 string2 12
lnnvl(condition):当条件为true时返回false
rank(hash_key, order_by_col1, order_by_col2 ...):与dense_rank类似,但是其会以1、2、2、2、5、6、7排序
row_number(hashkey)
select key1,key2,value,row_number(key1) as rank from (select key1,key2,value from test_table distribute by key1 sort by key1) t;
此函数同样不属于聚合函数,可看做rank的一个变种,给出1、2、3、4的标准行号,因此不需要比较部分字段是否相同以停留排序号。其依然依赖于distribute by和sort by之后的group结果,查询结果如下:
1 12 string1 1
1 2 string1 2
1 11 string1 3
1 12 string2 4
2 NULL string1 1
2 -21 string1 2
2 23 string1 3
2 14 string2 4
2 4 string2 5
3 32 string2 1
3 6 null 2
4 8 1
4 42 string2 2
5 54 string2 1
5 52 string1 2
5 NULL value5 3
6 64 string2 1
6 12 502 2
to_number(value, format_mask):string类型转换为number,按指定的format
NOTE:1.value必须为string类型
2.无参数时转为整数
3.format_mask必须为double或者字符串(字符串必须为带“$”且value也带“$”,否则抛出异常并返回NULL结果,但可以执行完成)
4.format_mask必须全由9组成,否则将返回空
5.当format_mask为double时,不会影响其结果的小数点位数(最多给整数加上.0)
chr(number_code):只能传入int,转为String.valueof((char) number_code),字符编码格式估计为内置的unicode
str_to_date(dateText,pattern):将输入的string类型的date按照pattern转为string类型的date,但是一定要以“yyyy-MM-dd HH:mm:ss”格式返回最终结果
date_format(dateText,pattern):将输入的string类型的date按照pattern转为string类型的date,以pattern格式返回最终结果,这是其与str_to_date的区别
WITH DEPT_COSTS AS--查询出部门的总工资 (SELECT D.DNAME, SUM(E.SAL) DEPT_TOTAL FROM DEPT D, EMP E WHERE E.DEPTNO = D.DEPTNO GROUP BY D.DNAME), AVE_COST AS --查询出部门的平均工资,在后一个WITH语句中可以引用前一个定义的WITH语句 (SELECT SUM(DEPT_TOTAL) / COUNT() AVG_SUM FROM DEPT_COSTS) SELECT FROM DEPT_COSTS DC WHERE DC.DEPT_TOTAL > (SELECT AC.AVG_SUM FROM AVE_COST AC) --进行比较
SELECT SalesOrderID, CustomerID,OrderDate, TotalDue, SUM(TotalDue) OVER (PARTITION BY CustomerID) AS CustomerTotal, SUM(TotalDue) OVER() AS GrandTotal, AVG(TotalDue) OVER (PARTITION BY CustomerID) AS AvgCustSale FROM Sales.SalesOrderHeader OuterQuery ORDER BY CustomerID;
SELECT a, b, c, SUM (Cube生成简单的 GROUP BY 聚合行、ROLLUP 超聚合行和交叉表格行) FROM T GROUP BY ROLLUP (a,b,c); 会为(a, b, c)、(a, b)和(a)值的每个唯一组合生成一个带有小计的行。还将计算一个总计行。
SELECT a, b, c, SUM () FROM T GROUP BY CUBE (a,b,c); 会为(a, b, c)、(a, b)、(a, c)、(b, c)、(a)、(b)和(c)值的每个唯一组合生成一个带有小计的行,还会生成一个总计行。
insert into TABLE_NAME(col1, col2, col3) values(value1, value2, value3);插入多条数据
insert into table TABLE_NAME select value1, value2, value3 from SRC_TABLE;指定插入的字段数量及顺序
insert into table TABLE_NAME(col2, col1) select value2, value1 from SRC_TABLE;
update TABLE_NAME set col1='value1', col2='value2' where rk like '123%';子查询更新
update TABLE_NAME set (col1, col2) = (select 'value1', 'value2' from TABLE_NAME where rk like '123%');
delete from TABLE_NAME where rk like '123%';