环境
  虚拟机:VMware 10
  Linux版本:CentOS-6.5-x86_64
  客户端:Xshell4
  FTP:Xftp4
  jdk1.8
  scala-2.10.4(依赖jdk1.8)
  spark-1.6

一、UDF:用户自定义函数。
可以自定义类实现UDFX接口

示例代码:
Java:

package com.wjy.df;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.api.java.UDF1;
import org.apache.spark.sql.api.java.UDF2;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType; public class UDF { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("UDF");
JavaSparkContext sc = new JavaSparkContext(conf);
SQLContext sqlContext = new SQLContext(sc); JavaRDD<String> rdd = sc.parallelize(Arrays.asList("xiaoming","xiaohong","xiaolei"));
JavaRDD<Row> rdd2 = rdd.map(new Function<String, Row>() {
private static final long serialVersionUID = 1L;
@Override
public Row call(String str) throws Exception {
return RowFactory.create(str);
}
}); /**
* 动态创建Schema方式加载DF
*/
List<StructField> fields = new ArrayList<StructField>();
fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
StructType schema = DataTypes.createStructType(fields);
DataFrame dataFrame = sqlContext.createDataFrame(rdd2, schema);
dataFrame.registerTempTable("user"); //定义一个统计字符串长度的函数
/**
* 根据UDF函数参数的个数来决定是实现哪一个UDF UDF1,UDF2。。。。UDF1xxx
*/
sqlContext.udf().register("StrLen", new UDF1<String, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Integer call(String str) throws Exception {
return str.length();
}
},DataTypes.IntegerType);
sqlContext.sql("select name ,StrLen(name) as length from user").show();
/*
* +--------+------+
| name|length|
+--------+------+
|xiaoming| 8|
|xiaohong| 8|
| xiaolei| 7|
+--------+------+
*/ sqlContext.udf().register("StrLen2", new UDF2<String, Integer, Integer>() {
private static final long serialVersionUID = 1L; @Override
public Integer call(String str, Integer num) throws Exception {
return str.length()+num;
}
}, DataTypes.IntegerType);
sqlContext.sql("select name ,StrLen2(name,10) as length from user").show();
/*
* +--------+------+
| name|length|
+--------+------+
|xiaoming| 18|
|xiaohong| 18|
| xiaolei| 17|
+--------+------+
*/ sc.stop();
} }

Scala:

package com.wjy.df

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.RowFactory
import org.apache.spark.sql.types.DataTypes
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.SQLContext object UDF {
def main(args:Array[String]):Unit={
val conf = new SparkConf().setMaster("local").setAppName("");
val sc = new SparkContext(conf);
val sqlContext = new SQLContext(sc);
val rdd = sc.makeRDD(Array("zhansan","lisi","wangwu"));
val row = rdd.map(x=>{
RowFactory.create(x);
});
val schema = DataTypes.createStructType(Array(StructField("name",StringType,true)));
val df = sqlContext.createDataFrame(row, schema);
df.show;//show方法可以没有()
df.registerTempTable("user"); //StrLen
sqlContext.udf.register("StrLen", (s:String)=>{s.length()});
sqlContext.sql("select name ,StrLen(name) as length from user").show; //StrLen2
sqlContext.udf.register("StrLen2", (s:String,i:Integer)=>{s.length()+i});
sqlContext.sql("select name ,StrLen2(name,10) as length from user").show; sc.stop();
}
}

二、UDAF:用户自定义聚合函数。
实现UDAF函数如果要自定义类要继承UserDefinedAggregateFunction类

示例代码:
Java:

package com.wjy.df;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.expressions.MutableAggregationBuffer;
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType; /**
* UDAF 用户自定义聚合函数
* @author root
*
*/
public class UDAF { public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("local").setAppName("UDAF");
JavaSparkContext sc = new JavaSparkContext(conf);
SQLContext sqlContext = new SQLContext(sc);
JavaRDD<String> parallelize = sc.parallelize(
Arrays.asList("zhangsan","lisi","wangwu","zhangsan","zhangsan","lisi"));
JavaRDD<Row> rowRDD = parallelize.map(new Function<String, Row>() {
private static final long serialVersionUID = 1L;
@Override
public Row call(String s) throws Exception {
return RowFactory.create(s);
}
}); List<StructField> fields = new ArrayList<StructField>();
fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
StructType schema = DataTypes.createStructType(fields);
DataFrame df = sqlContext.createDataFrame(rowRDD, schema);
df.registerTempTable("user"); /**
* 注册一个UDAF函数,实现统计相同值得个数
* 注意:这里可以自定义一个类继承UserDefinedAggregateFunction类也是可以的
*/
sqlContext.udf().register("StringCount",new UserDefinedAggregateFunction(){
private static final long serialVersionUID = 1L; /**
* 初始化一个内部的自己定义的值,在Aggregate之前每组数据的初始化结果
*/
@Override
public void initialize(MutableAggregationBuffer buffer) {
buffer.update(0, 0);
} /**
* 指定输入字段的字段及类型
*/
@Override
public StructType inputSchema() {
return DataTypes.createStructType(Arrays.asList(DataTypes.createStructField("name", DataTypes.StringType, true)));
} /**
* 更新 可以认为一个一个地将组内的字段值传递进来 实现拼接的逻辑
* buffer.getInt(0)获取的是上一次聚合后的值
* 相当于map端的combiner,combiner就是对每一个map task的处理结果进行一次小聚合
* 大聚和发生在reduce端.
* 这里即是:在进行聚合的时候,每当有新的值进来,对分组后的聚合如何进行计算
*/
@Override
public void update(MutableAggregationBuffer buffer, Row arg1) {
buffer.update(0, buffer.getInt(0)+1);
} /**
* 在进行聚合操作的时候所要处理的数据的结果的类型
*/
@Override
public StructType bufferSchema() {
return DataTypes.createStructType(Arrays.asList(DataTypes.createStructField("buffer", DataTypes.IntegerType, true)));
} /**
* 合并 update操作,可能是针对一个分组内的部分数据,在某个节点上发生的 但是可能一个分组内的数据,会分布在多个节点上处理
* 此时就要用merge操作,将各个节点上分布式拼接好的串,合并起来
* buffer1.getInt(0) : 大聚合的时候 上一次聚合后的值
* buffer2.getInt(0) : 这次计算传入进来的update的结果
* 这里即是:最后在分布式节点完成后需要进行全局级别的Merge操作
*/
@Override
public void merge(MutableAggregationBuffer buffer1, Row buffer2) {
buffer1.update(0, buffer1.getInt(0) + buffer2.getInt(0));
} /**
* 指定UDAF函数计算后返回的结果类型
*/
@Override
public DataType dataType() {
return DataTypes.IntegerType;
} /**
* 最后返回一个和dataType方法的类型要一致的类型,返回UDAF最后的计算结果
*/
@Override
public Object evaluate(Row row) {
return row.getInt(0);
} /**
* 确保一致性 一般用true,用以标记针对给定的一组输入,UDAF是否总是生成相同的结果。
*/
@Override
public boolean deterministic() {
return true;
} }); sqlContext.sql("select name ,StringCount(name) as strCount from user group by name").show();
sc.stop();
} }

Scala:

package com.wjy.df

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.types.DataTypes
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.RowFactory
import org.apache.spark.sql.expressions.UserDefinedAggregateFunction
import org.apache.spark.sql.types.IntegerType
import org.apache.spark.sql.expressions.MutableAggregationBuffer
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.DataType class MyUDAF extends UserDefinedAggregateFunction{
// 为每个分组的数据执行初始化值
def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = 0
} //输入数据的类型
def inputSchema: StructType = {
DataTypes.createStructType(Array(DataTypes.createStructField("input", StringType, true)))
} // 每个组,有新的值进来的时候,进行分组对应的聚合值的计算
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
buffer(0) = buffer.getAs[Int](0)+1
} // 聚合操作时,所处理的数据的类型
def bufferSchema: StructType = {
DataTypes.createStructType(Array(DataTypes.createStructField("aaa", IntegerType, true)))
} //最后merger的时候,在各个节点上的聚合值,要进行merge,也就是合并
def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer1(0) = buffer1.getAs[Int](0)+buffer2.getAs[Int](0)
} // 最终函数返回值的类型
def dataType: DataType = {
DataTypes.IntegerType
} // 最后返回一个最终的聚合值 要和dataType的类型一一对应
def evaluate(buffer: Row): Any = {
buffer.getAs[Int](0)
} //保持一致性
def deterministic: Boolean = {
true
}
} object UDAF {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
conf.setMaster("local").setAppName("udaf")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
val rdd = sc.makeRDD(Array("zhangsan","lisi","wangwu","zhangsan","lisi"))
val rowRDD = rdd.map { x => {RowFactory.create(x)} } val schema = DataTypes.createStructType(Array(DataTypes.createStructField("name", StringType, true)))
val df = sqlContext.createDataFrame(rowRDD, schema)
df.show()
df.registerTempTable("user")
/**
* 注册一个udaf函数
*/
sqlContext.udf.register("StringCount", new MyUDAF())
sqlContext.sql("select name ,StringCount(name) as count from user group by name").show()
sc.stop()
}
}

三、开窗函数
开窗函数格式:
row_number() over (partitin by XXX order by XXX)
注意:
row_number() 开窗函数是按照某个字段分组,然后取另一字段的前几个的值,相当于分组取topN;
如果SQL语句里面使用到了开窗函数,那么这个SQL语句必须使用HiveContext来执行,HiveContext默认情况下在本地无法创建。

示例代码:
Java:

package com.wjy.df;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.SaveMode;
import org.apache.spark.sql.hive.HiveContext; public class RowNumberWindowFun { public static void main(String[] args) {
SparkConf conf = new SparkConf();
conf.setAppName("windowfun");
conf.set("spark.sql.shuffle.partitions","1");
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"); /**
* 开窗函数格式:
* 【 row_number() over (partition by XXX order by XXX DESC) as rank】
* 注意:rank 从1开始
*/
/**
* 以类别分组,按每种类别金额降序排序,显示 【日期,种类,金额】 结果,如:
*
* 1 A 100
* 2 B 200
* 3 A 300
* 4 B 400
* 5 A 500
* 6 B 600
* 排序后:
* 5 A 500 --rank 1
* 3 A 300 --rank 2
* 1 A 100 --rank 3
* 6 B 600 --rank 1
* 4 B 400 --rank 2
* 2 B 200 --rank 3
*
*/
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(100);
/**
* 将结果保存到hive表sales_result
*/
result.write().mode(SaveMode.Overwrite).saveAsTable("sales_result");
sc.stop();
}
}

Scala:

package com.wjy.df

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.hive.HiveContext object RowNumberWindowFun {
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

【Spark-SQL学习之三】 UDF、UDAF、开窗函数的更多相关文章

  1. 【SQL学习笔记】排名开窗函数,聚合开窗函数(Over by)

    处理一些分组后,该组按照某列排序后 ,取其中某条完整数据的问题. 或 按照其中不同列分组后的聚合 比如 sum,avg之类. MSDN上语法: Ranking Window Functions < ...

  2. Spark(十三)SparkSQL的自定义函数UDF与开窗函数

    一 自定义函数UDF 在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_ ...

  3. spark SQL学习(案例-统计每日uv)

    需求:统计每日uv package wujiadong_sparkSQL import org.apache.spark.sql.{Row, SQLContext} import org.apache ...

  4. 【SQL】四种排序开窗函数

    一 .简单了解什么是开窗函数 什么是开窗函数,开窗函数有什么作用,特征是什么? 所谓开窗函数就是定义一个行为列,简单讲,就是在你查询的结果上,直接多出一列值(可以是聚合值或是排序号),特征就是带有ov ...

  5. spark SQL学习(综合案例-日志分析)

    日志分析 scala> import org.apache.spark.sql.types._ scala> import org.apache.spark.sql.Row scala&g ...

  6. spark SQL学习(认识spark SQL)

    spark SQL初步认识 spark SQL是spark的一个模块,主要用于进行结构化数据的处理.它提供的最核心的编程抽象就是DataFrame. DataFrame:它可以根据很多源进行构建,包括 ...

  7. spark SQL学习(案例-统计每日销售)

    需求:统计每日销售额 package wujiadong_sparkSQL import org.apache.spark.sql.types._ import org.apache.spark.sq ...

  8. spark SQL学习(spark连接 mysql)

    spark连接mysql(打jar包方式) package wujiadong_sparkSQL import java.util.Properties import org.apache.spark ...

  9. spark SQL学习(spark连接hive)

    spark 读取hive中的数据 scala> import org.apache.spark.sql.hive.HiveContext import org.apache.spark.sql. ...

  10. spark SQL学习(数据源之json)

    准备工作 数据文件students.json {"id":1, "name":"leo", "age":18} {&qu ...

随机推荐

  1. Urozero Autumn 2016. NCPC 2016

    A. Artwork 倒过来并查集维护即可. #include<cstdio> #include<algorithm> using namespace std; const i ...

  2. Django模型操作常用方法

    1.Save() 基本方法:object.save() save顾名思义是保存的意思,在django中既可以进行新增也可以进行修改操作.具体判定的算法如下: 1.如果对象的主键属性为一个求值为True ...

  3. css 文本设置

    常用的应用文本的css样式: (1)color 设置文字和颜色,如:color:red; (2)font-size 设置文字的大小,如:font-size:20px; (3)font-family 设 ...

  4. 解决Tomcatt下连接数据库的classNoFount问题

    在数据库连接单独使用的时候.即作为一个独立类建立在mian方法中,可以正确的使用.例:连接MySql数据库 import java.sql.*; public class SQLtest { // J ...

  5. <c:forEach var="role" items="[entity.Role@d54d4d, entity.Role@1c61868, entity.Role@6c58db, entity.Role@13da8a5]"> list 集合数据转换异常

    <c:forEach var="role" items="[entity.Role@d54d4d, entity.Role@1c61868, entity.Role ...

  6. bootstrap-treeview分级展示列表树的实现

    html页面: 要引用 "/webapp/common/css/bootstrap-treeview.css" "/webapp/common/js/bootstrap- ...

  7. Python全栈-magedu-2018-笔记6

    第三章 - Python 内置数据结构 bytes.bytearray Python3引入两个新类型 bytes 不可变字节序列 bytearray 字节数组 可变 bytes.bytearray 字 ...

  8. request之LIstener监听器

    要实现监听request内置对象,必须实现一个接口javax.servlet.ServletRequsetListener. 代码如下: package cn.wangkai.listener; im ...

  9. Python 学习笔记5 变量-列表

    列表是python常用的一种变量. 是由一些列按照特定顺序排列的元素组成的.你可以创建包含字母表中的所有字母,数字.可以将任何东西都加入到列表中. 通常情况下,列表中都包含多个元素,所以建议变量的名称 ...

  10. Word图片、表格添加题注

    1.首先为图片.表格添加题注: 2.通过交叉引用,如图**和图片.表的编号相关联起来: