代码之家  ›  专栏  ›  技术社区  ›  Alex

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

  •  0
  • Alex  · 技术社区  · 6 年前

    目前我有两个数据集,一个是父数据集,一个是子数据集。子数据集包含可以链接到父表的“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\u number()将windowSpec应用于子表。over(),如:

        child.withColumn("rank1", row_numbers().over(w1))
             .withColumn("rank2", row_numbers().over(w2))
    

    我的问题是,稍后,当我需要连接父表时,我需要连接两次,一次用于 parentId=id && rank1=1 ,另一个用于 parentId=id && rank2=1

    我想知道是否有一种方法可以只加入一次,这样会更有效率。 或者我错误地使用了窗口功能,有更好的方法吗?

    谢谢

    1 回复  |  直到 6 年前
        1
  •  2
  •   Raphael Roth    6 年前

    您可以先加入,然后使用groupBy而不是窗口函数,这可能会起作用(未测试,因为未提供编程数据帧):

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