Spark提供了一个特殊的NULL
安全等于运算符
numbersDf .join(lettersDf, numbersDf("numbers") <=> lettersDf("numbers")) .drop(lettersDf("numbers"))
+-------+-------+
|numbers|letters|
+-------+-------+
| 123| abc|
| 456| def|
| null| zzz|
| | hhh|
+-------+-------+
小心不要在Spark 1.5或更早版本中使用它.在Spark 1.6之前,它需要一个笛卡尔积(SPARK-11111 - 快速零安全连接).
在Spark 2.3.0或更高版本中,您可以Column.eqNullSafe
在PySpark中使用:
numbers_df = sc.parallelize([ ("123", ), ("456", ), (None, ), ("", ) ]).toDF(["numbers"]) letters_df = sc.parallelize([ ("123", "abc"), ("456", "def"), (None, "zzz"), ("", "hhh") ]).toDF(["numbers", "letters"]) numbers_df.join(letters_df, numbers_df.numbers.eqNullSafe(letters_df.numbers))
+-------+-------+-------+
|numbers|numbers|letters|
+-------+-------+-------+
| 456| 456| def|
| null| null| zzz|
| | | hhh|
| 123| 123| abc|
+-------+-------+-------+
并%<=>%
在SparkR中:
numbers_df <- createDataFrame(data.frame(numbers = c("123", "456", NA, ""))) letters_df <- createDataFrame(data.frame( numbers = c("123", "456", NA, ""), letters = c("abc", "def", "zzz", "hhh") )) head(join(numbers_df, letters_df, numbers_df$numbers %<=>% letters_df$numbers))
numbers numbers letters
1 456 456 def
2 zzz
3 hhh
4 123 123 abc
使用SQL(Spark 2.2.0+),您可以使用IS NOT DISTINCT FROM
:
SELECT * FROM numbers JOIN letters
ON numbers.numbers IS NOT DISTINCT FROM letters.numbers
这也可以与DataFrame
API 一起使用:
numbersDf.alias("numbers")
.join(lettersDf.alias("letters"))
.where("numbers.numbers IS NOT DISTINCT FROM letters.numbers")
val numbers2 = numbersDf.withColumnRenamed("numbers","num1") //rename columns so that we can disambiguate them in the join val letters2 = lettersDf.withColumnRenamed("numbers","num2") val joinedDf = numbers2.join(letters2, $"num1" === $"num2" || ($"num1".isNull && $"num2".isNull) ,"outer") joinedDf.select("num1","letters").withColumnRenamed("num1","numbers").show //rename the columns back to the original names