在Spark 1.6/Scala中,获取与聚合相关的列值

在Spark 1.6/Scala中,获取与聚合相关的列值,scala,apache-spark,dataframe,spark-dataframe,Scala,Apache Spark,Dataframe,Spark Dataframe,假设我有一个包含三列的数据框: itemid, date, price 1, 2017-05-18, $1.10 2, 2017-05-18, $2.20 1, 2017-04-12, $0.90 1, 2017-03-29, $1.00 现在,我想按itemid分组,获取最早的日期,并获取与最早日期匹配的价格。我们可以假设itemid,date是唯一的 上述输入的输出为: 1, 2017-03-29, $1.00 2, 2017-05-18, $2.20 在SQL中,我可以使用自联接来实现

假设我有一个包含三列的数据框:

itemid, date, price
1, 2017-05-18, $1.10
2, 2017-05-18, $2.20
1, 2017-04-12, $0.90
1, 2017-03-29, $1.00
现在,我想按itemid分组,获取最早的日期,并获取与最早日期匹配的价格。我们可以假设itemid,date是唯一的

上述输入的输出为:

1, 2017-03-29, $1.00
2, 2017-05-18, $2.20
在SQL中,我可以使用自联接来实现这一点—首先为每个itemid选择最小日期,然后选择日期与最小日期匹配的价格和日期

如何在Scala Spark数据帧中表达这一点?
如果答案仍然涉及自连接,Spark 1.6中的DataFrame查询执行器是否足够智能,不能实际实现连接?

一种方法是使用类似于以下内容的SparkSQL窗口函数:

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

val df = Seq(
    (1, "2017-05-18", 1.10),
    (2, "2017-05-18", 2.20),
    (1, "2017-04-12", 0.90),
    (1, "2017-03-29", 1.00)
  ).toDF(
    "itemid", "date", "price"
  ).as[(Integer, String, Double)]

// Add earliest date by itemid via window function and
// keep only rows with earliest date by itemid
val df2 = df.withColumn("earliestDate", min("date").over(
    Window.partitionBy("itemid")
  )).
  where($"date" === $"earliestDate")

df2.show
+------+----------+-----+------------+
|itemid|      date|price|earliestDate|
+------+----------+-----+------------+
|     1|2017-03-29|  1.0|  2017-03-29|
|     2|2017-05-18|  2.2|  2017-05-18|
+------+----------+-----+------------+

谢谢你的解决方案。事实证明,这有点类似于自联接方法-因为itemid,date已经是一个保证的唯一键,我可以使用标准聚合按日期计算id的最小价格,然后重新联接。也就是说,我可以使用unique键而不是row id,也可以使用groupBy而不是windowing。@Jon Watte,是的,使用groupBy和带有itemid的自联接,日期是唯一的,不需要创建唯一列。事实上,在这个简单的例子中,不需要自连接,因此如果使用窗口函数,当然不需要创建唯一的rowid。我已经更新了我的答案。