Spark join产生错误的结果

时间:2016-03-21 13:09:39

标签: scala apache-spark dataframe apache-spark-sql

在可能提交错误之前提交此处。我使用的是Spark 1.6.0。

这是我正在处理的问题的简化版本。我已经过滤了一个表格,然后我尝试使用该子集和主表格进行左外连接,匹配所有列。

我在主表中只有2行,而在过滤表中只有一行。我希望结果表只包含子集中的单行。

scala> a.join(b, $"filta" === $"a" and $"filtb" === $"b" and a("c") === b("c"), "left_outer").show
16/03/21 12:50:00 WARN Column: Constructing trivially true equals predicate, 'c#18232 = c#18232'. Perhaps you need to use aliases.
+-----+-----+---+---+---+---+
|filta|filtb|  c|  a|  b|  c|
+-----+-----+---+---+---+---+
|    a|    b|  1|  a|  b|  1|
+-----+-----+---+---+---+---+

我根本没想到这个结果。我期待第一排,但不是第二排。我怀疑它是零安全的平等,所以我没有试过它。

scala> a.withColumn("newc", $"c").join(b, $"filta" === $"a" and $"filtb" === $"b" and $"newc" === b("c"), "left_outer").show
+-----+-----+---+----+---+---+---+
|filta|filtb|  c|newc|  a|  b|  c|
+-----+-----+---+----+---+---+---+
|    a|    b|  1|   1|  a|  b|  1|
|    a|    b|  1|   1|  a|  b|  2|
+-----+-----+---+----+---+---+---+

好的,那是我预期的结果,但后来我对这个警告产生了怀疑。这里有一个单独的StackOverflow问题来处理这个警告:Spark SQL performing carthesian join instead of inner join

所以我创建了一个避免警告的新列。

{{1}}

但现在结果又错了! 我有很多无效的平等检查,并且警告不是致命的,所以我没有看到与此一起工作的明确途径。

这种行为是一个错误,还是这种预期的行为?如果预料到,为什么?

1 个答案:

答案 0 :(得分:4)

如果您想要预期的行为,请在名称上使用join

val b = Seq(("a", "b", 1), ("a", "b", 2)).toDF("a", "b", "c")
val a = b.where("c = 1")

a.join(b, Seq("a", "b", "c")).show
// +---+---+---+
// |  a|  b|  c|
// +---+---+---+
// |  a|  b|  1|
// +---+---+---+

或别名:

val aa = a.alias("a")
val bb = b.alias("b")

aa.join(bb, $"a.a" === $"b.a" && $"a.b" === $"b.b" && $"a.c" === $"b.c")

您也可以使用<=>

aa.join(bb, $"a.a" <=> $"b.a" && $"a.b" <=> $"b.b" && $"a.c" <=> $"b.c")

据我记得,在一段时间内,这是一个简单平等的特例。这就是为什么你得到正确的结果,尽管有警告。

第二种行为看起来确实像是一个与您的数据中仍然有a.c这一事实相关的错误。看起来它在b.c之前被下游挑选,并且评估条件实际上是a.newc = a.c

val expr = $"filta" === $"a" and $"filtb" === $"b" and $"newc" === $"c"
a.withColumnRenamed("c", "newc").join(b, expr, "left_outer")