Spark SQL使用substring函数出现类型不匹配错误如何解决
问题原因
- 首先你混淆了Spark SQL函数和Scala原生方法的签名差异:
org.apache.spark.sql.functions.substring提供两类重载,一类接收(Column, Int, Int),仅适用于后两个参数是固定字面量的场景;另一类接收(Column, Column, Column),适用于参数是动态列计算结果的场景。你传入的instr(...) +17是列运算表达式,返回值永远是Column类型,不可能转为固定的字面量Int,你做的强转操作本身是无效的,因为Column是对全表每行计算逻辑的抽象,无法在Driver端直接转为固定值。 - 报错的直接诱因大概率是你没有正确导入Spark的
substring函数,编译器默认匹配了Scala原生String类的substring方法,才会提示要求入参为Int类型。 - 你的代码还存在字段名笔误:计算起始位置时误用了
manuscriptpolicy_ext_vehicledescription字段,和你要切割的vehicledescription字段不一致,会导致后续逻辑错误。
修复方案
首先确认导入Spark SQL函数依赖:
import org.apache.spark.sql.functions._
修正笔误后直接使用Column类型作为substring的入参即可,Spark原生支持该重载:
val registrationNumber = pc_policy_df.select( col("vehicledescription"), when( col("subproduct_ext") === "SpecialRiskOwnDamage" && instr(col("vehicledescription"), "Registration No.:") === 0, "" ) .when( col("subproduct_ext") === "SpecialRiskOwnDamage" && instr(col("vehicledescription"), "Registration No.:") > 0, trim( substring( col("vehicledescription"), instr(col("vehicledescription"), "Registration No.:") + 17, locate(";", col("vehicledescription"), instr(col("vehicledescription"), "Registration No.:") + 17) - (instr(col("vehicledescription"), "Registration No.:") + 17) ) ) ) .otherwise("registrationnumber") .as("R_NUMBER") )
如果使用的Spark版本较低,不支持substring接收Column类型参数,可以用expr函数直接写SQL表达式实现,写法更简洁:
trim(expr("substring(vehicledescription, instr(vehicledescription, 'Registration No.:') + 17, locate(';', vehicledescription, instr(vehicledescription, 'Registration No.:') + 17) - (instr(vehicledescription, 'Registration No.:') + 17))"))
内容的提问来源于stack exchange,提问作者Julie
相关产品推荐
相关产品推荐

