天天看点

SparkCore / SparkSQL中窗口函数RANK, DENSE_RANK, ROW_NUMBER的区别

RANK, DENSE_RANK, ROW_NUMBER都是把表中的行按分区内的排序标上序号,但有一点差别:

RANK:可以生成不连续的序号,比如按分数排序,第一第二都是100分,第三名98分,那第一第二就会显示序号1,第三名显示序号3。

DENSE_RANK: 生成连续的序号,在上一例子中,第一第二并列显示序号1,第三名会显示序号2。

ROW_NUMBER: 顾名思义就是行的数值,在上一例子中,第一第二第三将会显示序号为1,2,3。

下面的例子帮助理解,按年级分组,分数降序排列,分别新建列RANK, DENSE_RANK, ROW_NUMBER:

考试成绩排名

姓名 年级 分数 RANK DENSE_RANK ROW_NUMBER
张三 一年级 100 1 1 1
李四 一年级 100 1 1 2
王五 一年级 98 3 2 3
小明 二年级 100 1 1 1
小芳 二年级 95 2 2 2
小民 二年级 90 3 3 3

实现代码:

package SparkSQLScala

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._

object TestWindowFunction {
  def main(args: Array[String]): Unit = {
    val sparkSession = SparkSession.builder().master("local").appName("TestWindownFunction").getOrCreate()
    sparkSession.sparkContext.setLogLevel("ERROR")
//  创建测试数据
    val ScoreDetailDF = sparkSession.createDataFrame(Seq(
      ("王五", "一年级", 98),
      ("李四", "一年级", 100),
      ("小民", "二年级", 90),
      ("小明", "二年级", 100),
      ("张三", "一年级", 100),
      ("小芳", "二年级", 95)
    )).toDF("name", "grade", "score")

    //    SparkSQL 方法实现
    ScoreDetailDF.createOrReplaceTempView("ScoreDetail")
    sparkSession.sql("SELECT * , " +
      "RANK() OVER (PARTITION BY grade ORDER BY score DESC) AS rank, " +
      "DENSE_RANK() OVER (PARTITION BY grade ORDER BY score DESC) AS dense_rank, " +
      "ROW_NUMBER() OVER (PARTITION BY grade ORDER BY score DESC) AS row_number " +
      "FROM ScoreDetail").show()

    //    DataFrame API 实现
    val windowSpec = Window.partitionBy("grade").orderBy(col("score").desc)
    ScoreDetailDF.select(col("name"),
      col("grade"),
      col("score"),
      rank().over(windowSpec).as("rank"),
      dense_rank().over(windowSpec).as("dense_rank"),
      row_number().over(windowSpec).as("row_number")
    ).show()

  }

}
           

输出结果:

+----+-----+-----+----+----------+----------+

|name|grade|score|rank|dense_rank|row_number|

+----+-----+-----+----+----------+----------+

|  李四|  一年级|  100|   1|         1|         1|

|  张三|  一年级|  100|   1|         1|         2|

|  王五|  一年级|   98|   3|         2|         3|

|  小明|  二年级|  100|   1|         1|         1|

|  小芳|  二年级|   95|   2|         2|         2|

|  小民|  二年级|   90|   3|         3|         3|

+----+-----+-----+----+----------+----------+

继续阅读