【Spark征服之路-3.6-Spark-SQL核心编程(五)】

自定义函数:

UDF:

val sparkConf = new SparkConf().setMaster("local\*" ).setAppName("SQLDemo" )
// 创建 SparkSession 对象
val spark :SparkSession = SparkSession.builder ().config(sparkConf).getOrCreate()

import spark.implicits._
// 读取 json 文件
val df : DataFrame = spark.read.json("Spark-SQL/input/user.json" )

spark.udf.register("addName" ,(x:String)=>"Name:" +x)

df.createOrReplaceTempView("people" )
spark.sql("select addName(username),age from people" ).show()

spark.stop()

UDAF(自定义聚合函数)

强类型的 Dataset 和弱类型的 DataFrame 都提供了相关的聚合函数, 如 count(),

countDistinct(),avg(),max(),min()。除此之外,用户可以设定自己的自定义聚合函数。Spark3.0之前我们使用的是UserDefinedAggregateFunction作为自定义聚合函数,从 Spark3.0 版本后可以统一采用强类型聚合函数 Aggregator

实验需求:计算平均工资

实现方式一:RDD

val sparkconf: SparkConf = new SparkConf().setAppName("app" ).setMaster("local\*" )
val sc: SparkContext = new SparkContext(conf)
val resRDD: (Int, Int) = sc.makeRDD(List (("zhangsan" , 20), ("lisi" , 30), ("wangw u " ,40))).map {
case (name, salary) => {
(salary, 1)
}
}.reduce {
(t1, t2) => {
(t1._1 + t2._1, t1._2 + t2._2)
}
}
println (resRDD._1/resRDD._2)
// 关闭连接
sc.stop()

实现方式二:弱类型UDAF

class MyAverageUDAF extends UserDefinedAggregateFunction{
def inputSchema: StructType =
StructType (Array (StructField ("salary" ,IntegerType)))
// 聚合函数缓冲区中值的数据类型 (salary,count)
def bufferSchema: StructType = {

StructType (Array (StructField ("sum" ,LongType),StructField ("count" ,LongType)))
}
// 函数返回值的数据类型
def dataType: DataType = DoubleType
// 稳定性:对于相同的输入是否一直返回相同的输出。
def deterministic: Boolean = true
// 函数缓冲区初始化
def initialize(buffer: MutableAggregationBuffer): Unit = {
// 存薪资的总和
buffer(0) = 0L
// 存薪资的个数
buffer(1) = 0L
}
// 更新缓冲区中的数据
def update(buffer: MutableAggregationBuffer,input: Row): Unit = {
if (!input.isNullAt(0)) {
buffer(0) = buffer.getLong(0) + input.getInt(0)
buffer(1) = buffer.getLong(1) + 1
}
}
// 合并缓冲区
def merge(buffer1: MutableAggregationBuffer,buffer2: Row): Unit = {
buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0)
buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1)
}
// 计算最终结果
def evaluate(buffer: Row): Double = buffer.getLong(0).toDouble /
buffer.getLong(1)
}

val sparkconf: SparkConf = new SparkConf().setAppName("app" ).setMaster("local\*" )
val spark:SparkSession = SparkSession.builder ().config(conf).getOrCreate()

import spark.implicits._
val res :RDD(String,Int)= spark.sparkContext.makeRDD(List (("zhangsan" , 20), ("lisi" , 30), ("wangwu" ,40)))

val df :DataFrame = res.toDF("name" ,"salary" )
df.createOrReplaceTempView("user" )
var myAverage = new MyAverageUDAF
// spark 中注册聚合函数
spark.udf.register("avgSalary" ,myAverage)
spark.sql("select avgSalary(salary) from user" ).show()

// 关闭连接
spark.stop()

实现方式三:强类型UDAF

case class Buff(var sum:Long,var cnt:Long)
class MyAverageUDAF extends AggregatorLong,Buff,Double{
override def zero: Buff = Buff (0,0)
override def reduce(b: Buff, a: Long): Buff = {
b.sum += a
b.cnt += 1
b
}
override def merge(b1: Buff, b2: Buff): Buff = {
b1.sum += b2.sum
b1.cnt += b2.cnt
b1
}
override def finish(reduction: Buff): Double = {
reduction.sum.toDouble/reduction.cnt
}
override def bufferEncoder: EncoderBuff = Encoders.product
override def outputEncoder: EncoderDouble = Encoders.scalaDouble

}

val sparkconf: SparkConf = new SparkConf().setAppName("app" ).setMaster("local\*" )
val spark:SparkSession = SparkSession.builder ().config(conf).getOrCreate()

import spark.implicits._
val res :RDD(String,Int)= spark.sparkContext.makeRDD(List (("zhangsan" , 20), ("lisi" , 30), ("wangwu" ,40)))

val df :DataFrame = res.toDF("name" ,"salary" )
df.createOrReplaceTempView("user" )
var myAverage = new MyAverageUDAF
// spark 中注册聚合函数
spark.udf.register("avgSalary" ,functions.udaf (myAverage))
spark.sql("select avgSalary(salary) from user" ).show()

// 关闭连接
spark.stop()

相关推荐
smilejingwei3 小时前
CodeBuddy+SQLazy 编写复杂 SQL 详解
sql·codebuddy·sqlazy
阿里云大数据AI技术5 小时前
阿里云 EMR Daft AI Function:用 DataFrame 表达式搞定大模型调用与多模态向量化
人工智能·spark
蒲公英eric10 小时前
从布尔盲注到参数化查询:DVWA SQL 盲注模块完整漏洞分析教程
sql·web安全·ai·dvwa·ai安全·sql 盲注
今天AI了吗11 小时前
MCP 协议打通 AI 与国产数据库,SQL 调优全流程一站式闭环
数据库·人工智能·sql
灯澜忆梦11 小时前
【MySQL11】进阶篇 | 索引_#3使用规则
数据库·sql·mysql·性能优化
BD_Marathon11 小时前
部署Spark
大数据·javascript·spark
Blossom i12 小时前
Python+spark2.0+Hadoop机器学习与大数据实战第十一章:Python Spark的集成开发环境
大数据·hadoop·spark
云技纵横12 小时前
线上接口突然超时,怎么判断卡在 Nginx、线程池、连接池还是 SQL?
后端·sql·mysql
sugar__salt13 小时前
MyBatis ③动态 SQL 完全指南 —— 从条件拼接到批量操作
java·sql·mybatis
BD_Marathon14 小时前
开发Spark应用程序
大数据·ajax·spark