Spark(十三)SparkSQL的自定义函数UDF与开窗函数
一 自定义函数UDF
在Spark中,也支持Hive中的自定义函数。自定义函数大致可以分为三种:
- UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等
- UDAF(User- Defined Aggregation Funcation),用户自定义聚合函数,类似在group by之后使用的sum,avg等
- UDTF(User-Defined Table-Generating Functions),用户自定义生成函数,有点像stream里面的flatMap
自定义一个UDF函数需要继承UserDefinedAggregateFunction类,并实现其中的8个方法
示例
import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types.{DataType, StringType, StructField, StructType} object GetDistinctCityUDF extends UserDefinedAggregateFunction{
/**
* 输入的数据类型
* */
override def inputSchema: StructType = StructType(
StructField("status",StringType,true) :: Nil
)
/**
* 缓存字段类型
* */
override def bufferSchema: StructType = {
StructType(
Array(
StructField("buffer_city_info",StringType,true)
)
)
}
/**
* 输出结果类型
* */
override def dataType: DataType = StringType
/**
* 输入类型和输出类型是否一致
* */
override def deterministic: Boolean = true
/**
* 对辅助字段进行初始化
* */
override def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer.update(0,"")
}
/**
*修改辅助字段的值
* */
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
//获取最后一次的值
var last_str = buffer.getString(0)
//获取当前的值
val current_str = input.getString(0)
//判断最后一次的值是否包含当前的值
if(!last_str.contains(current_str)){
//判断是否是第一个值,是的话走if赋值,不是的话走else追加
if(last_str.equals("")){
last_str = current_str
}else{
last_str += "," + current_str
}
}
buffer.update(0,last_str) }
/**
*对分区结果进行合并
* buffer1是机器hadoop1上的结果
* buffer2是机器Hadoop2上的结果
* */
override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
var buf1 = buffer1.getString(0)
val buf2 = buffer2.getString(0)
//将buf2里面存在的数据而buf1里面没有的数据追加到buf1
//buf2的数据按照,进行切分
for(s <- buf2.split(",")){
if(!buf1.contains(s)){
if(buf1.equals("")){
buf1 = s
}else{
buf1 += s
}
}
}
buffer1.update(0,buf1)
}
/**
* 最终的计算结果
* */
override def evaluate(buffer: Row): Any = {
buffer.getString(0)
}
}
注册自定义的UDF函数为临时函数
def main(args: Array[String]): Unit = {
/**
* 第一步 创建程序入口
*/
val conf = new SparkConf().setAppName("AralHotProductSpark")
val sc = new SparkContext(conf)
val hiveContext = new HiveContext(sc)
//注册成为临时函数
hiveContext.udf.register("get_distinct_city",GetDistinctCityUDF)
//注册成为临时函数
hiveContext.udf.register("get_product_status",(str:String) =>{
var status =
for(s <- str.split(",")){
if(s.contains("product_status")){
status = s.split(":")().toInt
}
}
})
}
二开窗函数
row_number() 开窗函数是按照某个字段分组,然后取另一字段的前几个的值,相当于 分组取topN
如果SQL语句里面使用到了开窗函数,那么这个SQL语句必须使用HiveContext来执行,HiveContext默认情况下在本地无法创建。
开窗函数格式:
row_number() over (partitin by XXX order by XXX)
java:
SparkConf conf = new SparkConf();
conf.setAppName("windowfun");
JavaSparkContext sc = new JavaSparkContext(conf);
HiveContext hiveContext = new HiveContext(sc);
hiveContext.sql("use spark");
hiveContext.sql("drop table if exists sales");
hiveContext.sql("create table if not exists sales (riqi string,leibie string,jine Int) "
+ "row format delimited fields terminated by '\t'");
hiveContext.sql("load data local inpath '/root/test/sales' into table sales");
/**
* 开窗函数格式:
* 【 rou_number() over (partitin by XXX order by XXX) 】
*/
DataFrame result = hiveContext.sql("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");
result.show();
sc.stop();
scala:
val conf = new SparkConf()
conf.setAppName("windowfun")
val sc = new SparkContext(conf)
val hiveContext = new HiveContext(sc)
hiveContext.sql("use spark");
hiveContext.sql("drop table if exists sales");
hiveContext.sql("create table if not exists sales (riqi string,leibie string,jine Int) "
+ "row format delimited fields terminated by '\t'");
hiveContext.sql("load data local inpath '/root/test/sales' into table sales");
/**
* 开窗函数格式:
* 【 rou_number() over (partitin by XXX order by XXX) 】
*/
val result = hiveContext.sql("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");
result.show();
sc.stop()
Spark(十三)SparkSQL的自定义函数UDF与开窗函数的更多相关文章
- SQL ServerOVER 子句,over开窗函数,SQL SERVER 开窗函数
https://technet.microsoft.com/zh-cn/library/ms189461(v=sql.105).aspx http://www.cnblogs.com/85538649 ...
- SQL Server聚合函数与聚合开窗函数 (转载)
以下面这个表的数据作为示例. 什么是聚合函数?聚合函数:聚合函数就是对一组值进行计算后返回单个值(即分组).聚合函数在计算时都会忽略空值(null).所有的聚合函数均为确定性函数.即任何时候使用一组相 ...
- SQL Server聚合函数与聚合开窗函数
以下面这个表的数据作为示例. 什么是聚合函数? 聚合函数:聚合函数就是对一组值进行计算后返回单个值(即分组).聚合函数在计算时都会忽略空值(null). 所有的聚合函数均为确定性函数.即任何时候使用一 ...
- SQL Server排名函数与排名开窗函数
什么是排名函数?说实话我也不甚清楚,我知道 order by 是排序用的,那么什么又是排名函数呢? 接下来看几个示例就明白了. 首先建立一个表,随便插入一些数据. ROW_NUMBER 函数:直接排序 ...
- 【SQL学习笔记】排名开窗函数,聚合开窗函数(Over by)
处理一些分组后,该组按照某列排序后 ,取其中某条完整数据的问题. 或 按照其中不同列分组后的聚合 比如 sum,avg之类. MSDN上语法: Ranking Window Functions < ...
- SparkSQL中的自定义函数UDF
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- spark开窗函数
源文件内容示例: http://bigdata.beiwang.cn/laoli http://bigdata.beiwang.cn/laoli http://bigdata.beiwang.cn/h ...
- hive常用函数 wordCount--Hive窗口函数1.1.1 聚合开窗函数聚合开窗函数实战
第三天笔记 第三天笔记 SQL练习Hive 常用函数关系运算数值计算条件函数日期函数重点!!!字符串函数Hive 中的wordCount1.1 Hive窗口函数1.1.1 聚合开窗函数聚合开窗函数实战 ...
- Oracle开窗函数 over()(转)
copy文链接:http://blog.csdn.net/yjjm1990/article/details/7524167#,http://www.2cto.com/database/201402/2 ...
随机推荐
- kubernetes挂载ceph rbd和cephfs的方法
目录 k8s挂载Ceph RBD PV & PVC方式 创建secret 创建PV 创建PVC 创建deployment挂载PVC StorageClass方式 创建secret 创建Stor ...
- P2243 电路维修
P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和Jam ...
- P3007 [USACO11JAN]大陆议会The Continental Cowngress
P3007 [USACO11JAN]大陆议会The Continental Cowngress 题意: 给出 n 个法案, m 头牛的意见, 每头牛有两个表决 格式为 "支持或反对某法案&q ...
- 利用 Dijit 组件框架打造丰富的用户界面
原文出处:Joe Lennon 从头开始学习 Dojo,第 3 部分 利用 Dijit 组件框架打造丰富的用户界面 Dijit 是什么? Dijit 是 Dojo 工具包的富组件用户界面库.这些组件完 ...
- Nginx基础配置指令
nginx.conf文件的结构 ... #全局块 events{ #events块 ... } http{ #http块 ... #http全局块 server{ #server块 ... #serv ...
- 跨域ajax请求携带cookie
通过withCredentials 方式: getCompanySubject: function () { return axios.get(this.apiUrls.getCompanySubje ...
- 高性能流媒体服务器EasyDarwin
标准RTSP拉模式直播(EasyRelayModule):适合内部监控 分布式部署(EasyCMSModule):负载均衡主要是用Reids作为负载
- 关于mysql 5.7版本“报[Err] 1093 - You can't specify target table 'XXX' for update in FROM clause”错误的bug
不同于oracle和sqlserver,mysql并不支持在更新某个表的数据时又查询了它,而查询的数据又做了更新的条件,因此我们需要使用如下的语句绕过: , notice_code ) a) ; 本地 ...
- Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))
题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...
- 天梯赛 L2-011. (二叉树) 玩转二叉树
题目链接 题目描述 给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列.所谓镜面反转,是指将所有非叶结点的左右孩子对换.这里假设键值都是互不相等的正整数. 输入格 ...