Spark-汇总和汇总具有父记录的子级

时间:2020-06-19 14:44:38

标签: dataframe apache-spark dataset aggregation

我处理具有树状结构的数据。每个父母可以有多个孩子。父母没有有关孩子的信息,但每个孩子都知道其父母。此外,每个孩子都知道其完整路径-这是一串串联的父代标识符,因此每个记录都知道其在树中的级别。该记录具有以下结构:

id  | parent_id | path
--- + --------- + ------
11  | 1         | 1-11
12  | 1         | 1-12
121 | 12        | 1-12-121

现在,我必须读取表,按ID分组,并对bigint类型的列value求和。最重要的事实是只有叶子-没有子元素的元素才具有指定值,并且每个父元素都必须是其所有子元素值的总和。最初,所有父母的值都等于0。

分组之前:

Root
| - Parent 1 (value = 0)
| - - Child 11 (value = 1)
| - - Child 12 (value = 1)
| - - Parent 13 (value = 0)
| - - - Child 131 (value = 2)
| - - - Child 132 (value = 1)
| - Parent 2 (value = 0)
| - - Child 21 (value = 2)
| - - Child 22 (value = 1)

分组结果:

Root
| - Parent 1 (value = 5 (1 + 1 + 3))
| - - Child 11 (value = 1)
| - - Child 12 (value = 1)
| - - Parent 13 (value = 3 (2 + 1))
| - - - Child 131 (value = 2)
| - - - Child 132 (value = 1)
| - Parent 2 (value = 3 (2 + 1))
| - - Child 21 (value = 2)
| - - Child 22 (value = 1)

这是非常重要的要求:我无法在内存中收集此数据和组,因为数据集确实很大,因此我必须使用数据集或数据框来完成

1 个答案:

答案 0 :(得分:1)

如果我理解正确,那么您只对每个节点的值总和感兴趣。在这种情况下,您只需要查看某个节点何时出现在路径之一中,并为相应的节点添加所有此类值即可。一个火花版本将是:

scala> val df = spark.sql(s"""
  select
    col1 as id,
    col2 as parent_id,
    col3 as path,
    col4 as value
  from values
    (11, 1, "1-11", 1),
    (12, 1, "1-12", 1),
    (13, 1, "1-13", 0),
    (131, 13, "1-13-131", 2),
    (132, 13, "1-13-132", 1)
""")


scala> (df
 .withColumn("path_arr", split(col("path"), "-"))
 .select($"value", explode($"path_arr").as("node"))
 .groupBy("node")
 .sum()
 .orderBy($"node")
).show

产生:

+----+----------+
|node|sum(value)|
+----+----------+
|   1|         5|
|  11|         1|
|  12|         1|
|  13|         3|
| 131|         2|
| 132|         1|
+----+----------+