1、UDF函数的使用
1、注册时直接写逻辑
ss.udf.register("length",(x:String)=>(x.length))
2、udaf函数的使用(弱类型是spark2.x)
1、继承UserDefinedAggregateFunction类,复写八个方法。session.udf.register("函数名",new MyUDF());注册
2、八个方法:
inputSchema 输入类型
bufferSchema 缓冲区类型
dataType 输出类型
deterministic 稳定性函数,传入相同参数结果是否一样。
initialize 缓冲区初始化函数
update 如何更新缓冲区
merge 多节点下不同节点缓冲区如何合并
evalute 基于缓冲区如何计算得出结果
package com.lirong
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types._
import org.apache.spark.sql.{DataFrame, Row, SparkSession}
public class MyUDAF extends UserDefinedAggregateFunction {
//输入类型
def inputSchema: StructType = {
DataTypes.createStructType(Array(
DataTypes.createStructField("input", LongType, true)
)
)
}
// 缓冲区类型
def bufferSchema: StructType = {
DataTypes.createStructType(Array(
DataTypes.createStructField("total", LongType, true),
DataTypes.createStructField("count", LongType, true)
)
)
}
// 输出类型
def dataType: DataType = {
DataTypes.LongType
}
//稳定性函数:多次运行,相同的输入是否得到相同的输出。true为是
def deterministic: Boolean = {
true
}
//缓冲区初始化函数
def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer.update(0,0L) //参数1为角标,参数2为值
buffer.update(1,0L) //参数1为角标,参数2为值
}
// 如何更新缓冲区
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
buffer.update(0,buffer.getLong(0)+input.getLong(0))
buffer.update(1,buffer.getLong(1)+1)
}
// 多节点下各个节点缓冲区合并
def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer.update(0,buffer1.getLong(0)+buffer2.getLong(0))
buffer.update(1,buffer1.getLong(1)+buffer2.getLong(1))
}
//缓冲区数据如何进行计算
def evaluate(buffer: Row): Any = {
buffer.getLong(0)/buffer.getLong(1)
}
}
3、udaf函数的使用(强类型spark 3.x)
1、继承aggregator函数,泛型为输入输出缓冲区类型,复写六个方法。session.udf.register("函数名",functions.udf(new MyUDF()));注册
2、六个方法:
zero:缓冲区初始化函数。
reduce 如何更新缓冲区
merge 多节点洗啊不同节点缓冲区如何合并
evalute 基于缓冲区如何计算得出结果
bufferEncoder 缓冲区编码操作,解决跨节点传输问题
outputEncoder 输出编码操作,解决跨节点传输问题
3、其实spark 2.x也能使用强类型的udaf函数,但注册函数时需要以DSL方式将UDAF定义成查询语句的一列,比较麻烦。
4、弱类型不会对输入数据的类型做判断,传入啥就用啥计算,类型不对会报错。而强类型不会。
开窗函数
开窗函数
所谓开窗函数,就是在对数据进行分组,然后给数据打上一个组内的序号。
如果要实现分组求top n,只需要对排序的字段进行过滤即可。
标准格式:
row_number() over (partitin by xxx order by yyy) z
解释:
partitin by xxx:
根据xxx字段进行分组。
order by yyy:
根据yyy字段进行排序。
z:
别名。可用于过滤
示例:
select riqi,leibie,jine from (
select riqi,leibie,jine,
row_number() over (partition by leibie order by jine desc) rank from sales) t
where t.rank<=3;
###求每类商品中销售金额排名前3的日期。
MySQL 8之后也支持开窗函数。