Spark Dataset筛选col("a")不等于col("b")返回0条结果问题求助
问题原因
- NULL值三值逻辑问题:Spark SQL遵循三值逻辑规则,任意值与NULL做等于、不等于比较的返回结果都是
UNKNOWN,filter算子仅会保留判断结果为true的记录。只要参与比较的两列中有任意一列为NULL,不等判断就不会命中这类记录,比如a为NULL、b为1时,a !== b的返回值不是true,不会被筛选出来。 - 数据类型不匹配问题:如果列a和列b的数据类型不一致,比较时会触发隐式类型转换,可能导致肉眼可见的不等值被转换为相等,比如列a为String类型存储
"123",列b为Int类型存储123,隐式转换后二者会被判定为相等,不会被筛选出来。 - 字符串隐性差异问题:如果参与比较的是字符串类型列,可能存在肉眼不可识别的差异,比如首尾空格、换行符、大小写差异、全角半角字符差异等,导致实际值不等但肉眼判断一致。
解决方法
对应不同原因可采用对应方案处理:
- 针对NULL值场景:
如果需要将其中一列为NULL、另一列非NULL的记录也判定为不等,可使用空安全相等的反向判断,代码示例:
dataset.filter(!col("a").eqNullSafe(col("b")));
也可显式对NULL值填充默认值后再做比较,代码示例:
dataset.filter(coalesce(col("a"), lit("自定义默认值")).notEqual(coalesce(col("b"), lit("自定义默认值"))));
- 针对数据类型不匹配场景:
先通过dataset.printSchema()确认两列数据类型,显式转换为同一类型后再比较,示例(将列a转换为列b的类型后比较):
dataset.filter(col("a").cast(col("b").dataType()).notEqual(col("b")));
- 针对字符串隐性差异场景:
按需对字符串做预处理清洗后再比较,比如去除首尾空格、统一大小写等,代码示例:
dataset.filter(trim(lower(col("a"))).notEqual(trim(lower(col("b")))));
内容的提问来源于stack exchange,提问作者Himanshu Goyal
相关产品推荐
相关产品推荐

