如何在Spark中按条件将多行合并为单行并计算金额
Spark按借贷标识计算调整后金额并重组DataFrame实现方案
实现思路
核心是利用Spark的分布式分组聚合能力处理每个memo_id的借贷金额,避免低效的循环操作:
- 将贷方(C)金额转为负数,借方(D)保持正数,求和后直接得到
computed_amount - 按
memo_id和memo_attr_1分组(二者在原始数据中一一对应) - 重命名列并整理输出结构
完整Scala实现代码
import org.apache.spark.sql.functions._ def compute(memoData: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row]): org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = { memoData // 转换金额:借方金额为正,贷方金额为负 .withColumn("adjusted_amount", when(col("credit_or_debit") === "D", col("amount")).otherwise(-col("amount"))) // 按memo_id和memo_attr_1分组,聚合求和得到计算后金额 .groupBy("memo_id", "memo_attr_1") .agg(sum("adjusted_amount").alias("computed_amount")) // 根据计算后金额确定借贷标识(正数为借方D,负数为贷方C) .withColumn("credit_or_debit", when(col("computed_amount") > 0, "D").otherwise("C")) // 重命名memo_id为memo_number .withColumnRenamed("memo_id", "memo_number") // 调整列顺序与目标结构一致 .select("memo_number", "computed_amount", "credit_or_debit", "memo_attr_1") }
代码说明
- 金额转换:通过
when函数将贷方金额转为负数,确保后续求和逻辑等价于「借方总额 - 贷方总额」 - 分组聚合:利用
groupBy+sum完成分布式的金额计算,这是Spark最优的批量处理方式,远优于循环单条处理 - 借贷标识确定:根据计算后金额的正负判断最终标识,适配所有可能的金额结果(不仅限于示例中的正数场景)
- 列调整:重命名列并指定输出顺序,匹配目标DataFrame的结构
结果验证
运行上述compute函数后,输出的computedData将完全匹配目标数据结构:
| memo_number | computed_amount | credit_or_debit | memo_attr_1 |
|---|---|---|---|
| MEM_1 | 80 | D | X |
| MEM_2 | 150 | D | Y |
| MEM_3 | 300 | D | Z |
内容的提问来源于stack exchange,提问作者saurabh.kg001
相关产品推荐
相关产品推荐

