我正在使用Spark(Scala)来QA数据移动 - 将表从一个关系数据库移动到另一个关系数据库。QA 过程涉及在源表和目标表之间执行完全外部联接。
源表和目标表在以下键上的数据框中连接:
val joinColumns = for (i <- 0 to (sourceJoinFields.length - 1)) yield sourceDF.col(sourceJoinFields(i)) <=> targetDF.col(targetJoinFields(i))
val joinedDF = sourceDF.join(targetDF, joinColumns.reduce((_&&_)), "fullouter")
我使用以下逻辑来查找不匹配:
val mismatchColumns = for (i <- 0 to (sourceDF.columns.length-1)) yield (joinedDF.col(joinedDF.columns(i)) =!= joinedDF.col(joinedDF.columns(i+(sourceDF.columns.length))))
val mismatchedDF = joinedDF.filter(mismatchColumns.reduce((_||_)))
但是,如果完整外部联接的一端缺少密钥:
+--------------+--------------+--------------+--------------+
|source_key |source_field |target_key |target_field |
+--------------+--------------+--------------+--------------+
|null |null |XXX |XXX |
不会在不匹配的DF数据集中。
所以我的问题:=!=
运算符与<=>
运算符相反吗?它似乎不是,那么在这种情况下是否有运算符会返回 FALSE?我找不到有关任一运算符的太多文档。
IS NOT DISTINCT FROM
( <=>
) 的反义词是 IS DISTINCT FROM
( not(... <=> ...)
)。
import org.apache.spark.sql.not
val df = Seq(("foo", null), ("foo", "bar"), ("foo", "foo")).toDF("x", "y")
df.select(not($"x" <=> $"y"))
或
df.select(!($"x" <=> $"y"))
或
df.selectExpr("x IS DISTINCT FROM y")
都给出相同的结果:
+---------------+
|(NOT (x <=> y))|
+---------------+
| true|
| true|
| false|
+---------------+
当然,如果你有一个否定的析取:
(NOT P) OR (NOT Q)
你总是可以使用德摩根定律将其重写为对连词的否定
NOT(P AND Q)
因此:
not(joinColumns.foldLeft(lit(true))(_ and _))
应该工作得很好。