Dataframe Spark SQL:当groupBy()中的另一列为max value时,获取该列的值。agg()

Dataframe Spark SQL:当groupBy()中的另一列为max value时,获取该列的值。agg(),dataframe,apache-spark,apache-spark-sql,Dataframe,Apache Spark,Apache Spark Sql,我有一个如下所示的数据帧: root |-- value: int (nullable = true) |-- date: date (nullable = true) val result = df .filter(df("date")>= somedate && df("date")<= some other date) .groupBy(valueFromColumn1) .agg( max(date), min(valueFromColu

我有一个如下所示的数据帧:

root
 |-- value: int (nullable = true)
 |-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
    max(date),
    min(valueFromColumn2),
    Here I want to put valueFromColumn4 where date is max after the filter
 )
我想返回value,其中value是数据帧中的最新日期。 如果我需要创建groupBy和agg,这个问题会改变吗? 我的实际问题如下所示:

root
 |-- value: int (nullable = true)
 |-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
    max(date),
    min(valueFromColumn2),
    Here I want to put valueFromColumn4 where date is max after the filter
 )

输出sameple filter为date>=2006,date解决方案是使用结构将值和日期绑定在一起。它看起来是这样的:

root
 |-- value: int (nullable = true)
 |-- date: date (nullable = true)
val result = df
.filter(df("date")>= somedate && df("date")<= some other date)
.groupBy(valueFromColumn1)
.agg(
    max(date),
    min(valueFromColumn2),
    Here I want to put valueFromColumn4 where date is max after the filter
 )
val结果=df .filterdfdate>=somedate&&dfdate您可以将groupBy与结构一起使用:

或带有窗口:


您要执行的操作是在列1上分组的一组数据中排序。这是的完美用例,它对一组记录执行计算

在这里,我们可以对第1列上的窗口进行分区,并从每个这样的窗口中选择最大日期。让我们将windowedPartition定义为:

val windowedPartition = Window.partitionBy("col1").orderBy(col("date").desc)
然后我们可以在数据集上应用这个窗口函数来选择排名最高的行。我没有在下面的代码中添加过滤逻辑,因为我认为这不会带来任何复杂性,也不会影响解决方案

工作代码:

    scala> import org.apache.spark.sql.expressions.Window
    import org.apache.spark.sql.expressions.Window


    scala> val data = Seq(("a" , 1, 2006, 5), ("a", 5, 2018, 2), ("a", 3, 2000, 3), ("b", 13, 2007, 4)).toDF("col1", "col2", "date", "col4")
    data: org.apache.spark.sql.DataFrame = [col1: string, col2: int ... 2 more fields]


    scala> data.show
    +----+----+----+----+
    |col1|col2|date|col4|
    +----+----+----+----+
    |   a|   1|2006|   5|
    |   a|   5|2018|   2|
    |   a|   3|2000|   3|
    |   b|  13|2007|   4|
    +----+----+----+----+      

    scala> val windowedPartition = Window.partitionBy("col1").orderBy(col("date").desc)
    windowedPartition: org.apache.spark.sql.expressions.WindowSpec = org.apache.spark.sql.expressions.WindowSpec@39613474

    scala> data.withColumn("row_number", row_number().over(windowedPartition)).show
    +----+----+----+----+----------+
    |col1|col2|date|col4|row_number|
    +----+----+----+----+----------+
    |   b|  13|2007|   4|         1|
    |   a|   5|2018|   2|         1|
    |   a|   1|2006|   5|         2|
    |   a|   3|2000|   3|         3|
    +----+----+----+----+----------+


    scala> data.withColumn("row_number", row_number().over(windowedPartition)).where(col("row_number") === 1).show
    +----+----+----+----+----------+
    |col1|col2|date|col4|row_number|
    +----+----+----+----+----------+
    |   b|  13|2007|   4|         1|
    |   a|   5|2018|   2|         1|
    +----+----+----+----+----------+


    scala> data.withColumn("row_number", row_number().over(windowedPartition)).where(col("row_number") === 1).drop(col("row_number")).show
    +----+----+----+----+
    |col1|col2|date|col4|
    +----+----+----+----+
    |   b|  13|2007|   4|
    |   a|   5|2018|   2|
    +----+----+----+----+
我相信这将是一个比struct更具可扩展性的解决方案,因为如果列的数量增加,我们可能也必须在struct中添加这些列,在这个解决方案中,这种情况将得到解决

但有一个问题:
在o/p中,col2中的值应为5,因为col1=A对吗?col2的值是如何变为1的?

您能添加一些预期的输入和输出示例吗?添加了示例,希望对您有所帮助。谢谢。