一、row_number函数的用法:
(1)Spark 1.5.x版本以后,在Spark SQL和DataFrame中引入了开窗函数,其中比较常用的开窗函数就是row_number
该函数的作用是根据表中字段进行分组,然后根据表中的字段排序;其实就是根据其排序顺序,给组中的每条记录添
加一个序号;且每组的序号都是从1开始,可利用它的这个特性进行分组取top-n。
(2)如果SQL语句里面使用到了开窗函数,那么这个SQL语句必须使用HiveContext来执行,HiveContext默认情况下在
本地无法创建。
(3)row_number的格式:
ROW_NUMBER() OVER (PARTITION BY 'xxx' ORDER BY 'xxx' DESC) rank
二、利用row_number实现分组取top3
* 实验数据
* user表中:
* id age deptId
* 001 21 d1
* 002 23 d2
* 003 31 d1
* 004 27 d2
* 005 28 d1
* 006 25 d2
* 007 41 d1
* 008 33 d2
* 009 36 d1
* 010 42 d2
* 011 37 d1
* 012 24 d2
*
* 如果利用row_number()实现按deptId分组根据age降序取top-3,最后结果为:
* id age deptId
* 007 41 d1
* 011 37 d1
* 009 36 d1
* 010 42 d2
* 008 33 d2
* 006 25 d2
*/
public class OpenwidowFunctionDemo {
public static void main(String[] args){
//创建配置
SparkConf conf = new SparkConf()
.setAppName("openwindowFunctionDemo");
//创建提交spark应用的集群入口类对象
JavaSparkContext sc = new JavaSparkContext(conf);
//创建SQLContext对象
SQLContext sqlContext = new HiveContext(sc.sc());
//加载数据
sqlContext.sql("use spark");
sqlContext.sql("drop table if exists user");
sqlContext.sql("create table if not exists user (userId string,age int,deptId string) "
+ "row format delimited fields terminated by '\t'");
sqlContext.sql("load data local inpath '/home/user.txt' into table user");
String sql = "SELECT "
+"userId,"
+"age,"
+"deptId "
+"FROM ("
+"SELECT "
+"userId,"
+"age,"
+"deptId "
+"ROW_NUMBER() OVER (PARTITION BY deptId ORDER BY age DESC) rank"
+"FROM user"
+") tmp_user"
+"WHERE rank <= 3";
//执行查询
DataFrame df = sqlContext.sql(sql);
df.show();
//将结果写入Hive表中
df.write().mode(SaveMode.Overwrite).saveAsTable("user_top3_res");
sc.stop();
}
}