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

时间:2018-03-01 19:44:30

标签: apache-spark spark-dataframe apache-spark-dataset

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

由于

1 个答案:

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