繁体   English   中英

用于聚合和更新表中父子关系的值的 Spark 查询

[英]Spark query to aggregate and update values in a table for a parent child relationship

我有以下表格(每个表格还有其他列,但这里不需要)

项目表

      user_id, party_id, parent_user_id
        1,        X,      null
        2,        X,       1
        3,        X,       1
        4,        Z,       null
        5,        Z,       4
        6,        Y,       null
        7,        Y,       6
        8,        Y,       6
        1,        Y,       null

其中null parent_user_id表示其父用户,然后无论哪个列具有 parent_user_id,都表示其为子用户。

优先级表

      user_id, party_id, priority
          1,      X,     0.3 
          2,      X,     0.8
          3,      X,     0.5 
          4,      Z,     0.1
          5,      Z,     0.2
          6,      Y,     0.7
          7,      Y,     0.4
          8,      Y,     0.5
          1,      Y,     0.3

我想要做的是编写一个火花查询来转换优先级表,如下所示。 逻辑应该是,对于每个父用户及其子用户,计算其最大优先级,即 max(parent user priority, child user1 priority, child user2 priority, ....) 然后更改优先级以反映该父级的最大值及其所有子项(如下面更新表中所述)。

优先级表

      user_id, party_id, priority
          1,      X,     0.8 
          2,      X,     0.8
          3,      X,     0.8 
          4,      Z,     0.2
          5,      Z,     0.2
          6,      Y,     0.7
          7,      Y,     0.7
          8,      Y,     0.7
          1,      Y,     0.3

您如何编写火花作业来完成此任务? 您甚至如何首先编写一个基本的 sql 查询来完成此操作。

我的解决方案基于以下几点。

1) 根据user_idparty_id加入itempriority表。

2)用它的user_id替换null parent_user_id (这很神奇)

3) **如果需要,删除不必要的列。

4) 应用 window function 并在party_id中找到最大优先级。

val itemTbl = Seq((1, "X", None),
      (2, "X", Some(1)),
      (3, "X", Some(1)),
      (4, "Z", None),
      (5, "Z", Some(4)),
      (6, "Y", None),
      (7, "Y", Some(6)),
      (8, "Y", Some(6)),
      (1, "Y", None)).toDF("user_id", "party_id", "parent_user_id")


    val priorityTbl = Seq((1, "X", 0.3),
      (2, "X", 0.8),
      (3, "X", 0.5),
      (4, "Z", 0.1),
      (5, "Z", 0.2),
      (6, "Y", 0.7),
      (7, "Y", 0.4),
      (8, "Y", 0.5),
      (1, "Y", 0.3)).toDF("user_id", "party_id", "priority")

  //replace null parent_user_id with actual value in Item table.
    val replaceExp = when(col("parent_user_id") isNull, col("user_id")).otherwise(col("parent_user_id"))
    val itemTblModf = itemTbl.withColumn("parent_user_id", replaceExp)

val windowSpec = Window.partitionBy("party_id", "parent_user_id")
itemTblModf.join(priorityTbl, itemTbl("user_id") <=> priorityTbl("user_id") && itemTbl("party_id") <=> priorityTbl("party_id"))
  .drop(priorityTbl("user_id"))
  .drop(priorityTbl("party_id"))
  .withColumn("new_priority", max("priority") over windowSpec).show(200, false)

结果

+-------+--------+--------------+--------+------------+
|user_id|party_id|parent_user_id|priority|new_priority|
+-------+--------+--------------+--------+------------+
|1      |Y       |1             |0.3     |0.3         |
|1      |X       |1             |0.3     |0.8         |
|2      |X       |1             |0.8     |0.8         |
|3      |X       |1             |0.5     |0.8         |
|4      |Z       |4             |0.1     |0.2         |
|5      |Z       |4             |0.2     |0.2         |
|6      |Y       |6             |0.7     |0.7         |
|7      |Y       |6             |0.4     |0.7         |
|8      |Y       |6             |0.5     |0.7         |
+-------+--------+--------------+--------+------------+

我不会说我的解决方案非常有效,但它是一个可行的解决方案。使用 RDD 以更实用的方式也可以实现相同的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM