如何在Scala中结合使用select与case语句?SQL转Scala遇错求助
Spark SQL转Scala代码的正确写法及替代方案
先明确你原SQL的核心逻辑:当timestamp1大于timestamp2时,salary和manager列返回空值,否则保留原字段值。你写的Scala代码存在几个问题:
- 拼写错误:
timstamp2应为timestamp2(少了字母e) - 逻辑反转:原SQL是条件成立时返回null,你写的是条件成立时返回salary,逻辑搞反了
- 错误的空值表示:用字符串
"null"代替了SQL中的空值,应该用Spark的lit(null)或直接写null - 遗漏了
manager列的转换逻辑
修正后的withColumn写法
import org.apache.spark.sql.functions.{when, lit} df.select("jess", "mark", "timestamp1", "timestamp2", "salary", "manager") .withColumn("salary", when($"timestamp1" > $"timestamp2", lit(null)).otherwise($"salary")) .withColumn("manager", when($"timestamp1" > $"timestamp2", lit(null)).otherwise($"manager"))
更简洁的select直接构造写法
无需先选列再覆盖,直接在select环节完成所有字段转换:
import org.apache.spark.sql.functions.when df.select( $"jess", $"mark", $"timestamp1", $"timestamp2", when($"timestamp1" > $"timestamp2", null).otherwise($"salary").alias("salary"), when($"timestamp1" > $"timestamp2", null).otherwise($"manager").alias("manager") )
适合新手的selectExpr写法
如果熟悉SQL语法,用selectExpr可以直接写SQL风格的表达式,更直观:
df.selectExpr( "jess", "mark", "timestamp1", "timestamp2", "CASE WHEN timestamp1 > timestamp2 THEN NULL ELSE salary END AS salary", "CASE WHEN timestamp1 > timestamp2 THEN NULL ELSE manager END AS manager" )
额外注意点
- 建议一次性导入Spark常用函数:
import org.apache.spark.sql.functions._,避免逐个导入 - 如果字段名包含特殊字符或与关键字冲突,需要用反引号包裹,比如
$`timestamp1` lit(null)和直接写null在Spark中效果一致,前者更明确是构造空值字面量
内容的提问来源于stack exchange,提问作者Tanmay
相关产品推荐
相关产品推荐

