048 SparkSQL自定义UDAF函数
一:程序
1.需求
实现一个求平均值的UDAF。
这里保留Double格式化,在完成求平均值后与系统的AVG进行对比,观察正确性。
2.SparkSQLUDFDemo程序
package com.scala.it import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.{SparkConf, SparkContext} import scala.math.BigDecimal.RoundingMode object SparkSQLUDFDemo {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
.setMaster("local[*]")
.setAppName("udf")
val sc = SparkContext.getOrCreate(conf)
val sqlContext = new HiveContext(sc) // ==================================
// 写一个Double数据格式化的自定义函数(给定保留多少位小数部分)
sqlContext.udf.register(
"doubleValueFormat", // 自定义函数名称
(value: Double, scale: Int) => {
// 自定义函数处理的代码块
BigDecimal.valueOf(value).setScale(scale, RoundingMode.HALF_DOWN).doubleValue()
}) // 自定义UDAF
sqlContext.udf.register("selfAvg", AvgUDAF) sqlContext.sql(
"""
|SELECT
| deptno,
| doubleValueFormat(AVG(sal), 2) AS avg_sal,
| doubleValueFormat(selfAvg(sal), 2) AS self_avg_sal
|FROM hadoop09.emp
|GROUP BY deptno
""".stripMargin).show() }
}
3.AvgUDAF程序
package com.scala.it import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._ object AvgUDAF extends UserDefinedAggregateFunction{
override def inputSchema: StructType = {
// 给定UDAF的输出参数类型
StructType(
StructField("sal", DoubleType) :: Nil
)
} override def bufferSchema: StructType = {
// 在计算过程中会涉及到的缓存数据类型
StructType(
StructField("total_sal", DoubleType) ::
StructField("count_sal", LongType) :: Nil
)
} override def dataType: DataType = {
// 给定该UDAF返回的数据类型
DoubleType
} override def deterministic: Boolean = {
// 主要用于是否支持近似查找,如果为false:表示支持多次查询允许结果不一样,为true表示结果必须一样
true
} override def initialize(buffer: MutableAggregationBuffer): Unit = {
// 初始化 ===> 初始化缓存数据
buffer.update(0, 0.0) // 初始化total_sal
buffer.update(1, 0L) // 初始化count_sal
} override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
// 根据输入的数据input,更新缓存buffer的内容
// 获取输入的sal数据
val inputSal = input.getDouble(0) // 获取缓存中的数据
val totalSal = buffer.getDouble(0)
val countSal = buffer.getLong(1) // 更新缓存数据
buffer.update(0, totalSal + inputSal)
buffer.update(1, countSal + 1L)
} override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
// 当两个分区的数据需要进行合并的时候,该方法会被调用
// 功能:将buffer2中的数据合并到buffer1中
// 获取缓存区数据
val buf1Total = buffer1.getDouble(0)
val buf1Count = buffer1.getLong(1) val buf2Total = buffer2.getDouble(0)
val buf2Count = buffer2.getLong(1) // 更新缓存区
buffer1.update(0, buf1Total + buf2Total)
buffer1.update(1, buf1Count + buf2Count)
} override def evaluate(buffer: Row): Any = {
// 求返回值
buffer.getDouble(0) / buffer.getLong(1)
}
}
4.效果

二:知识点
1.udf注册

2.解释上面的update
重要的是两个参数的意思,不然程序有些看不懂。
所以,程序的意思是,第一位存储总数,第二位存储个数。

3.还要解释一个StructType的生成
在以前的程序中,是使用Array来生成的。如:

在上面的程序中,不是这种方式,使用集合的方式。

048 SparkSQL自定义UDAF函数的更多相关文章
- hive自定义udaf函数
自定义udaf函数的代码框架 //首先继承一个类AbstractGenericUDAFResolver,然后实现里面的getevaluate方法 public GenericUDAFEvaluator ...
- sparksql 自定义用户函数(UDF)
自定义用户函数有两种方式,区别:是否使用强类型,参考demo:https://github.com/asker124143222/spark-demo 1.不使用强类型,继承UserDefinedAg ...
- 047 SparkSQL自定义UDF函数
一:程序部分 1.需求 Double数据类型格式化,可以给定小数点位数 2.程序 package com.scala.it import org.apache.spark.{SparkConf, Sp ...
- 关于CDH5.2+ 添加hive自定义UDAF函数的方法
- Spark(十三)【SparkSQL自定义UDF/UDAF函数】
目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...
- 【Spark篇】---SparkSql之UDF函数和UDAF函数
一.前述 SparkSql中自定义函数包括UDF和UDAF UDF:一进一出 UDAF:多进一出 (联想Sum函数) 二.UDF函数 UDF:用户自定义函数,user defined functio ...
- Spark基于自定义聚合函数实现【列转行、行转列】
一.分析 Spark提供了非常丰富的算子,可以实现大部分的逻辑处理,例如,要实现行转列,可以用hiveContext中支持的concat_ws(',', collect_set('字段'))实现.但是 ...
- 自定义Hive函数
7. 函数 7.1 系统内置函数 查看系统自带的函数:show functions; 显示自带的函数的用法:desc function upper(函数名); 详细显示自带的函数的用法:desc fu ...
- 入门大数据---SparkSQL常用聚合函数
一.简单聚合 1.1 数据准备 // 需要导入 spark sql 内置的函数包 import org.apache.spark.sql.functions._ val spark = SparkSe ...
随机推荐
- python创建udp服务端和客户端
1.udp服务端server from socket import * from time import ctime HOST = '' PORT = 8888 BUFSIZ = 1024 ADDR ...
- css3 自定义滚动条样式
::-webkit-scrollbar :滚动条整体部分 ::-webkit-scrollbar-thumb :滚动条里面的小方块样式 ::-webkit-scrollbar-track 滚动条的轨道 ...
- liunx tomcat 运行模式apr
tomcat运行模式一共三种:bio.nio.apr 网上对这三种运行模式的解释外: bio运行模式:阻塞式I/O操作,表示Tomcat使用的是传统的Java I/O操作(即java.io包及其子包) ...
- python 面向对象编程(初级篇)
飞机票 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向过程编程最 ...
- Pod 找不到头文件 解决方法
在 BuildSetting 中 搜索 User Header Search Paths 然后在下面 User Header Search Paths 中添加 ${SRCROOT} 再将后面参数改为 ...
- AD9361框图
1. Fir滤波器的阶数为64或128 而内插或抽取因子为:1.2或4. HB1和HB2的内插或抽取因子为1或2而HB3的因子为1.2或3 BB_LPF为:三阶巴特沃斯低通滤波器,3dB点频率可编程, ...
- SpringBoot集成Shiro
Shiro是一个安全框架,控制登陆,角色权限管理(身份认证.授权.回话管理.加密) Shiro不会去维护用户,维护权限:这些需要通过realm让开发人员自己注入 1.在pom.xml中引入shiro的 ...
- DSB
Linux day01 计算机硬件知识整理 作业要求:整理博客,内容如下 编程语言的作用及与操作系统和硬件的关系 应用程序->操作系统->硬件 cpu->内存->磁盘 cpu与 ...
- Linux基础实操二
实操一: 1) 新建用户natasha uid为1000,gid为555,备注信息为“master” 2) 修改natasha用户的家目录为/Natasha 3) 查看用户信息配置文件的最后一行 ca ...
- java方法重载和重写
1.java的方法重载和重写,表示两种不同的类型.this关键字,出现在类的构造方法中,代表使用该构造方法所创建的对象.,this可以出现在实例方法中核构造方法中.但是不能出现在类方法中.实例方法只能 ...