Spark Java中otherwise子句内使用Group By聚合操作报错问题咨询
问题原因与解决方案
你的问题根源很明确:when/otherwise是Spark的列级表达式函数,要求每个分支返回Column类型,但你在otherwise里直接返回了一个Dataset<Row>(jmCto2.groupBy(...).agg(...)的结果),类型不匹配导致了这个报错。
为什么会报错?
functions.when()和otherwise()的作用是基于条件生成单个列的值,每个分支必须是可以直接作为列计算的表达式(比如字面量、字段引用、列函数调用)。而groupBy().agg()是用来生成一个全新的数据集的操作,它返回的是Dataset<Row>,不是单个列,Spark自然无法把一个数据集当作列的值来处理,所以抛出了"Unsupported literal type class org.apache.spark.sql.Dataset"的错误。
正确的解决思路
你需要先把聚合计算和条件分支分开,有两种常用的实现方式:
方式1:提前聚合再关联
先对jmCto2做预聚合,得到每个CONTRA1对应的eadfinal总和,再把这个聚合结果和你的join数据集关联,最后在otherwise里引用聚合后的列:
// 第一步:预计算每个CONTRA1的eadfinal总和 Dataset<Row> jmCto2Agg = jmCto2.groupBy(CONTRA1) .agg(functions.sum("eadfinal").alias("sum_eadfinal")); // 第二步:关联预聚合结果,再构造条件列 Dataset<Row> contrCapOk1 = contrCapOk.join(jmCto2, contrCapOk.col(CONTRA1).equalTo(jmCto2.col(CONTRA1)), "LEFT") .join(jmCto2Agg, contrCapOk.col(CONTRA1).equalTo(jmCto2Agg.col(CONTRA1)), "LEFT") .select( contrCapOk.col("*"), jmCto2.col("ind"), functions.when(jmCto2.col(CONTRA1).isNull(), functions.lit(NUEVES)) .when(jmCto2.col("ind").equalTo("N"), functions.lit(UNOS)) .otherwise(jmCto2Agg.col("sum_eadfinal")) .as("EAD") );
方式2:使用窗口函数
如果不想额外做一次join,可以用窗口函数在join后的数据集里直接计算每个CONTRA1的总和:
import org.apache.spark.sql.expressions.Window; // 定义窗口:按CONTRA1分组 Window contraWindow = Window.partitionBy(CONTRA1); Dataset<Row> contrCapOk1 = contrCapOk.join(jmCto2, contrCapOk.col(CONTRA1).equalTo(jmCto2.col(CONTRA1)), "LEFT") .select( contrCapOk.col("*"), jmCto2.col("ind"), functions.when(jmCto2.col(CONTRA1).isNull(), functions.lit(NUEVES)) .when(jmCto2.col("ind").equalTo("N"), functions.lit(UNOS)) .otherwise(functions.sum(jmCto2.col("eadfinal")).over(contraWindow)) .as("EAD") );
这两种方式都能实现你想要的逻辑:当CONTRA1不存在时返回NUEVES,当ind为"N"时返回UNOS,否则返回该CONTRA1对应的eadfinal总和。
内容的提问来源于stack exchange,提问作者Jose Maria Acevedo Reinoso
相关产品推荐
相关产品推荐

