从Spark sql Windows函数获得意外结果

时间:2017-09-30 13:48:46

标签: apache-spark apache-spark-sql

似乎Spark sql Window功能无法正常工作。 我在Hadoop集群中运行一个火花作业,HDFS块大小为128 MB Spark版本1.5 CDH 5.5

我的要求:

如果有多个记录具有相同的data_rfe_id,则按照最大seq_id和maxiumum service_id

获取单个记录

我看到在原始数据中有一些记录具有相同的data_rfe_id和相同的seq_id因此,我使用Window函数应用row_number以便我可以使用row_num过滤记录=== 1

但是当拥有庞大的数据集时,它似乎无法正常工作。我看到应用了相同的rowNumber。

为什么会这样?

在数据帧上应用窗口函数之前,是否需要重新洗牌?

我希望每个data_rfe_id

都有一个唯一的排名

我只想使用Window Function来实现这一点。

 import org.apache.spark.sql.expressions.Window
 import org.apache.spark.sql.functions.rowNumber
 .....

scala> df.printSchema
root
 |-- transitional_key: string (nullable = true)
 |-- seq_id: string (nullable = true)
 |-- data_rfe_id: string (nullable = true)
 |-- service_id: string (nullable = true)
 |-- event_start_date_time: string (nullable = true)
 |-- event_id: string (nullable = true)


 val windowFunction = Window.partitionBy(df("data_rfe_id")).orderBy(df("seq_id").desc,df("service_id").desc)
  val rankDF =df.withColumn("row_num",rowNumber.over(windowFunction))
  rankDF.select("data_rfe_id","seq_id","service_id","row_num").show(200,false)

预期结果:

 +------------------------------------+-----------------+-----------+-------+
  |data_rfe_id                         |seq_id           |service_id|row_num|
 +------------------------------------+-----------------+-----------+-------+
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695826          |4039       |1     |
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695821          |3356       |2     |
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695802          |1857       |3     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2156       |1     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2103       |2     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2083       |3     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2082       |4     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2076       |5     |

我按照上述代码获得的实际结果:

 +------------------------------------+-----------------+-----------+-------+
 |data_rfe_id                          |seq_id           |service_id|row_num|
 +------------------------------------+-----------------+-----------+-------+
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695826          |4039       |1     |
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695821          |3356       |1     |
 |9ih67fshs-de11-4f80-a66d-b52a12c14b0e|1695802          |1857       |1     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2156       |1     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2103       |1     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2083       |1     |
 |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2082       |1     |
  |23sds222-9669-429e-a95b-bc984ccf0fb0 |1695541          |2076       |1     |

有人能解释我为什么会得到这些意想不到的结果吗?以及如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

基本上你想要排序,在desc顺序中有seq_id和service_id。添加rangeBetween与您需要的范围。排名可能对你有用。以下是代码片段:

val windowFunction = Window.partitionBy(df("data_rfe_id")).orderBy(df("seq_id"),df("service_id")).desc().rangeBetween(-MAXNUMBER,MAXNUMBER))
val rankDF =df.withColumn( "rank", rank().over(windowFunction) )

当您使用较旧版本的spark时,不知道它是否可行。这里有windowSpec的问题是reference