什么是聚合函数
聚合,多对一,类似窗口聚合
- 用户自定义聚合函数(User-Defined Aggregate Functions,UDAF)可以把一个表中的数据,聚合成一个标量值
- 用户定义的聚合函数,是通过继承 AggregateFunction 抽象类实现的
聚合函数的实现
AggregationFunction要求必须实现的方法
createAccumulator()
accumulate()
getValue()
聚合函数的工作原理
- 首先,它需要一个累加器(Accumulator),用来保存聚合中间结果的数据结构;可以通过调用
createAccumulator()
方法创建空累加器 - 随后,对每个输入行调用函数的
accumulate()
方法来更新累加器 - 处理完所有行后,将调用函数的
getValue()
方法来计算并返回最终结果
代码实现
//实现自定义的AggregateFunction<结果值,中间状态>
public static class AvgTemp extends AggregateFunction<Double, Tuple2<Double,Integer>> {
//输出结果
@Override
public Double getValue(Tuple2<Double, Integer> acc) {
return acc.f0/acc.f1;
}
//初始化累加器
@Override
public Tuple2<Double, Integer> createAccumulator() {
return new Tuple2<Double,Integer>(0.0,0);
}
//必须实现一个accumulate(中间状态,传入的一条数据)方法,来数据之后更新状态
public void accumulate(Tuple2<Double,Integer> acc, Double temp){
acc.f0 += temp;
acc.f1 += 1;
}
}
测试用例
//流转换成表 Tuple3<String,Long,Double>
Table sourceTable = tableEnv.fromDataStream(dataStream, "f0 as id, f1 as ts, f2 as temp,pt.proctime");
//在环境中注册UDAF
AvgTemp avgTemp = new AvgTemp();
tableEnv.registerFunction("avgTemp",avgTemp);
//tableAPI
Table resultTable = sourceTable.groupBy("id")
.aggregate("avgTemp(temp) as avgtemp")
.select("id,avgtemp");
tableEnv.toRetractStream(resultTable, Row.class).print();
//SQL
tableEnv.createTemporaryView("sensor",sourceTable);
Table resultSqlTbale = tableEnv.sqlQuery("select id,avgTemp(temp) as avgtemp from sensor group by id");
tableEnv.toRetractStream(resultSqlTbale,Row.class).print();