一:程序

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函数的更多相关文章

  1. hive自定义udaf函数

    自定义udaf函数的代码框架 //首先继承一个类AbstractGenericUDAFResolver,然后实现里面的getevaluate方法 public GenericUDAFEvaluator ...

  2. sparksql 自定义用户函数(UDF)

    自定义用户函数有两种方式,区别:是否使用强类型,参考demo:https://github.com/asker124143222/spark-demo 1.不使用强类型,继承UserDefinedAg ...

  3. 047 SparkSQL自定义UDF函数

    一:程序部分 1.需求 Double数据类型格式化,可以给定小数点位数 2.程序 package com.scala.it import org.apache.spark.{SparkConf, Sp ...

  4. 关于CDH5.2+ 添加hive自定义UDAF函数的方法

  5. Spark(十三)【SparkSQL自定义UDF/UDAF函数】

    目录 一.UDF(一进一出) 二.UDAF(多近一出) spark2.X 实现方式 案例 ①继承UserDefinedAggregateFunction,实现其中的方法 ②创建函数对象,注册函数,在s ...

  6. 【Spark篇】---SparkSql之UDF函数和UDAF函数

    一.前述 SparkSql中自定义函数包括UDF和UDAF UDF:一进一出  UDAF:多进一出 (联想Sum函数) 二.UDF函数 UDF:用户自定义函数,user defined functio ...

  7. Spark基于自定义聚合函数实现【列转行、行转列】

    一.分析 Spark提供了非常丰富的算子,可以实现大部分的逻辑处理,例如,要实现行转列,可以用hiveContext中支持的concat_ws(',', collect_set('字段'))实现.但是 ...

  8. 自定义Hive函数

    7. 函数 7.1 系统内置函数 查看系统自带的函数:show functions; 显示自带的函数的用法:desc function upper(函数名); 详细显示自带的函数的用法:desc fu ...

  9. 入门大数据---SparkSQL常用聚合函数

    一.简单聚合 1.1 数据准备 // 需要导入 spark sql 内置的函数包 import org.apache.spark.sql.functions._ val spark = SparkSe ...

随机推荐

  1. LINUX用户、组、权限管理和归档压缩、时间、Ping

    一.用户与用户组管理.权限 1.用户文件/etc/passwd 2.用户密码/etc/shadow 3.组文件/etc/group 4.查看用户和组信息命令id 5.添加用户 useradd [-u ...

  2. CSS基础入门

    css基础语法 一.CSS格式 选择器{ 属性名:属性值; 属性名:属性值; } 选择器负责圈定范围,要修改的元素集合,花括号内的声明由属性名和属性值组成(key:value)的形式,用于设定具体样式 ...

  3. Confluence 6 虚拟文件和文件夹

    在取消点赞事件中,你可能会遇到 WebDAV  客户端的问题或者不稳定的情况,你可以启用访问自动创建(虚拟)文件和文件夹. 备注: 在默认情况下,这个选项隐藏在 'WebDAV Configurati ...

  4. SpringMVC环境搭建

    Spring MVC为展现层提供的基于MVC设计理念的优秀Web框架,是目前最主流的MVC框架之一. Spring 3.0之后完全超越Struts2,称为最优秀的MVC框架.学完SpringMVC之后 ...

  5. 1283: 骨牌铺方格(zzuli)

    Problem Description 在2×n的一个长方形方格中,用一个1× 2的骨牌铺满方格,输入n ,输出铺放方案的总数.例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图: Input ...

  6. cf1132G 线段树解分区间LIS(一种全新的线段树解LIS思路)+单调栈

    /* 给定n个数的数列,要求枚举长为k的区间,求出每个区间的最长上升子序列长度 首先考虑给定n个数的数列的LIS求法:从左往右枚举第i点作为最大点的贡献, 那么往左找到第一个比a[i]大的数,设这个数 ...

  7. bzoj 3129

    非常好的一道数学题,考察了大量数论和组合数学的知识 在做本题之前强烈建议先完成下列两个背景知识: ①: bzoj 2142礼物 因为本题的一部分数据需要利用到拓展卢卡斯定理,而礼物是拓展卢卡斯定理的裸 ...

  8. Java 写一段字符到指定的文本文档中,如果该文本文档不存在,则创建该文本文档

    写一段字符到指定的文本文档中,如果该文本文档不存在,则创建该文本文档 import java.io.File; import java.io.FileNotFoundException; import ...

  9. Axure实现多用户注册验证

    *****多用户登录验证***** 一.(常规想法)方法:工作量较大,做起来繁琐 1.当用户名和密码相同时怎么区分两者,使用冒号和括号来区分: eg. (admin:123456)(123456:de ...

  10. java提取出一个字符串里面的Double类型数字

    String str="hh\n1\n22\n798.809\n0.89\n";         String regex="\\d+(?:\\.\\d+)?" ...