sparksql 开窗函数怎么用
row_number方法,相当于groupTopN。分组排序应用非常广泛。
package com.dt.spark
import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.{SparkContext, SparkConf}
object SparkSQLWindowFunctionOps {
def main(args:Array[String]) {
val conf: SparkConf = new SparkConf().setAppName("SparkSQLWindowFunctionOps").setMaster("spark://Master:7077")
val sc = new SparkContext(conf)
val hiveContext = new HiveContext(sc) //构建SQL上下文!
为什么我们要使用开窗函数?
什么时候会用到开窗函数呢?下面介绍使用场景: 表test1数据如下: 现在我们有需求:查出它们每个年级(class)的平均分数,预期结果格式如下: 我们可以看到,根据年级class求avg()聚合后的 数据会变少一条 ,但是,我们 既要显示聚合前的数据又要显示聚合后的数据 ,这个时候就要使用开窗函数。 测试: 查询数据: 返回结果: 出现的两个问题: 1.如果我们在partition by class加一个order by id会出现什么问题 返回结果: 可以看到class为1的两条avg值不一致,这是因为order by id是来一条数据处理一条,所以第一条class为1的数据来的只能是99/1=99。 我们可能会这样想,先查询出数据放到一张临时表,然后在开窗,根据class分区,再根据id排序,可是结果并不是根据id全局有序的 返回结果: 因为它是按照分区排序的,所以是分区内有序。 另外,我们和group by分组做个对比 原始数据如下 我们可能会想,为什么同样在这里使用了聚合函数sum(),数据条数变少了,我们为什么没有开窗呢? 这里使用group by进行了分组,根据id和时间进行分组。 那我们想是否上面也可以使用group by 而不使用开窗呢? 如下sql是否可以呢? 返回结果: 答案是不可以。因为我们select了多个字段,所以我们要根据多个字段来分组,class相同再根据id分组,id相同再根据score分组。导致我们不能仅仅根据class分组,也就导致最后分组出来的数据除了class、id、score都相同的两条数据能够聚合,否则都是单条数据自己聚合。 所以我们要使用group by就只能选取单个字段 返回结果