在不使用两个连接的情况下获取第一个和最后一个项目
Get first and last item without using two joins
目前我有两个数据集,一个是parent,一个是child。 Child 数据集包含 "parentId" 列,可以 link 到 parent table。 Child 数据集保存有关人的行为的数据,parent table 保存有关人的数据。我想获取一个包含人员信息和他的 first/last 操作的数据集。
数据集如下所示:
Parent:
id | name | gender
111| Alex | Male
222| Alice| Female
Child:
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 |
目前我可以使用两个 window 函数来实现这一点,例如:
WindowSepc w1 = Window.partitionBy("parentId").orderBy(col("time").asc())
WindowSepc w2 = Window.partitionBy("parentId").orderBy(col("time").desc())
并使用 row_number().over() 将 windowSpec 应用到 child table,例如:
child.withColumn("rank1", row_numbers().over(w1))
.withColumn("rank2", row_numbers().over(w2))
我遇到的问题是稍后,当我需要加入 parent table 时,我需要加入两次,一次用于 parentId=id && rank1=1
,另一次用于parentId=id && rank2=1
有没有办法只加入一次,效率会高很多。
或者我错误地使用了Window函数,有更好的方法吗?
谢谢
您可以先加入,然后使用 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")
)
目前我有两个数据集,一个是parent,一个是child。 Child 数据集包含 "parentId" 列,可以 link 到 parent table。 Child 数据集保存有关人的行为的数据,parent table 保存有关人的数据。我想获取一个包含人员信息和他的 first/last 操作的数据集。
数据集如下所示:
Parent:
id | name | gender
111| Alex | Male
222| Alice| Female
Child:
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 |
目前我可以使用两个 window 函数来实现这一点,例如:
WindowSepc w1 = Window.partitionBy("parentId").orderBy(col("time").asc())
WindowSepc w2 = Window.partitionBy("parentId").orderBy(col("time").desc())
并使用 row_number().over() 将 windowSpec 应用到 child table,例如:
child.withColumn("rank1", row_numbers().over(w1))
.withColumn("rank2", row_numbers().over(w2))
我遇到的问题是稍后,当我需要加入 parent table 时,我需要加入两次,一次用于 parentId=id && rank1=1
,另一次用于parentId=id && rank2=1
有没有办法只加入一次,效率会高很多。 或者我错误地使用了Window函数,有更好的方法吗?
谢谢
您可以先加入,然后使用 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")
)