在不使用两个连接的情况下获取第一个和最后一个项目

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")
   )