目前我有两个数据集,一个是父数据集,一个是子数据集。子数据集包含可以链接到父表的“parentId”列。子数据集保存有关人的动作的数据,父表保存有关人的数据。我想获得一个包含人物信息和他的第一个/最后一个动作的数据集。
数据集看起来像这样:
父:
id | name | gender
111| Alex | Male
222| Alice| Female
孩子:
parentId | time | Action
111 | 12:01| Walk
111 | 12:03| Run
222 | 12:04| Walk
111 | 12:05| Jump
111 | 12:06| Run
我想要制作的数据集是:
id | name | gender | firstAction | lastAction |
111| Alex | Male | Walk | Run |
222| Alice| Female | Walk | Walk |
目前我可以使用两个窗口函数来实现这一点,例如:
WindowSepc w1 = Window.partitionBy("parentId").orderBy(col("time").asc())
WindowSepc w2 = Window.partitionBy("parentId").orderBy(col("time").desc())
并使用row_number()。over()将windowSpec应用于子表,如:
child.withColumn("rank1", row_numbers().over(w1))
.withColumn("rank2", row_numbers().over(w2))
我遇到的问题是,稍后,当我需要加入父表时,我需要加入两次,一次用于parentId=id && rank1=1
,另一次用于parentId=id && rank2=1
我想知道是否有办法只加入一次,效率会更高。 或者我错误地使用了Window函数,还有更好的方法吗?
由于
答案 0 :(得分:2)
您可以先加入,然后使用groupBy而不是window-functions,这可以工作(未测试,因为没有提供编程数据帧):
parent
.join(child,$"parentId"===$"id")
.groupBy($"parentId",$"name",$"gender")
.agg(
min(struct($"time",$"action")).as("firstAction"),
max(struct($"time",$"action")).as("lastAction")
)
.select($"parentId",
$"name",
$"gender",
$"firstAction.action".as("firstAction"),
$"lastAction.action".as("lastAction")
)