gre*_*hor 6 sql null apache-spark spark-dataframe
filter在包含null值的基本scala集合上,具有以下(且非常直观)的行为:
scala> List("a", "b", null).filter(_ != "a")
res0: List[String] = List(b, null)
Run Code Online (Sandbox Code Playgroud)
但是,我很惊讶地发现以下过滤器删除了火花数据帧中的空值:
scala> val df = List(("a", null), ( "c", "d")).toDF("A", "B")
scala> df.show
+---+----+
| A| B|
+---+----+
| a|null|
| c| d|
+---+----+
scala> df.filter('B =!= "d").show
+---+---+
| A| B|
+---+---+
+---+---+
Run Code Online (Sandbox Code Playgroud)
如果要保留null值,我应该添加
df.filter('B =!= "d" || 'B.isNull).show
+---+----+
| A| B|
+---+----+
| a|null|
+---+----+
Run Code Online (Sandbox Code Playgroud)
就个人而言,我认为默认情况下删除空值非常容易出错。为什么选择这个?为何在api文档中未明确说明?我想念什么吗?
这是因为 SQL 的标准不是空安全的 - 所以 Spark SQL 遵循这一点(但不是 Scala)。
尽管 Spark 数据帧具有空安全的相等性
scala> df.filter($"B" <=> null).show
+---+----+
| A| B|
+---+----+
| a|null|
+---+----+
scala> df.filter(not($"B" <=> "d")).show
+---+----+
| A| B|
+---+----+
| a|null|
+---+----+
Run Code Online (Sandbox Code Playgroud)
编辑中的注意事项:默认情况下不是空安全的要点是允许空作为测试结果。缺失值是否等于“c”?我们不知道。一个缺失值是否等于另一个缺失值?我们也不知道。但是在过滤器中,null 是假的。