在SparkSQL
1.6 API(标量)中,Dataframe
具有用于相交和除的功能,但不具有相差的功能。显然,联合和除外的组合可以用来产生差异:
df1.except(df2).union(df2.except(df1))
但是这似乎有点尴尬。以我的经验,如果有些事情看起来很尴尬,那么有更好的方法可以做到这一点,尤其是在Scala中。
您始终可以将其重写为:
df1.unionAll(df2).except(df1.intersect(df2))
虽然很严重,但是UNION
,INTERSECT
和EXCEPT
/ MINUS
几乎是一组标准的SQL组合运算符。我不知道任何提供开箱即用的XOR之类的系统的系统。最有可能的原因是,使用其他三个实现起来并不容易,并且在那里没有太多要优化的地方。
为什么不下面?
df1.except(df2)
注意EXCEPT(或MINUS只是EXCEPT的别名)会对结果进行去重复。因此,如果您希望“ except”集(您提到的差异)+“ intersect”集等于原始数据帧,请考虑保留重复项的此功能请求:
https://issues.apache.org/jira/browse/SPARK-21274
正如我在那写的,“ EXCEPT ALL”可以在Spark SQL中重写为:
SELECT a,b,c
FROM tab1 t1
LEFT OUTER JOIN
tab2 t2
ON (
(t1.a, t1.b, t1.c) = (t2.a, t2.b, t2.c)
)
WHERE
COALESCE(t2.a, t2.b, t2.c) IS NULL
如果您正在寻找Pyspark解决方案,则应使用减去()docs。
此外,unionAll在2.0中已弃用,请改用union()。
df1.union(df2).subtract(df1.intersect(df2))
我认为使用左联接然后过滤出空值可能会更有效。
df1.join(df2, Seq("some_join_key", "some_other_join_key"),"left")
.where(col("column_just_present_in_df2").isNull)