获取第一个和最后一个项目而不使用两个连接

问题描述 投票:0回答:1

目前我有两个数据集,一个是父数据集,一个是子数据集。子数据集包含可以链接到父表的“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函数,有更好的方法吗?

谢谢

apache-spark spark-dataframe apache-spark-dataset
1个回答
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")
   )
© www.soinside.com 2019 - 2024. All rights reserved.