在Spark中执行DataFrame自联接的最干净,最有效的语法

时间:2016-03-27 14:46:11

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

在标准SQL中,当您将表连接到自身时,可以为表创建别名以跟踪您引用的列:

<tr>

使用Spark SELECT a.column_name, b.column_name... FROM table1 a, table1 b WHERE a.common_field = b.common_field; API可以通过两种方式来实现相同的目标:

解决方案#1:重命名列

对于 this question ,有几种不同的方法可以解决这个问题。这个只重命名具有特定后缀的所有列:

DataFrame

例如,你可以这样做:

df.toDF(df.columns.map(_ + "_R"):_*)

解决方案#2:将引用复制到df.join(df.toDF(df.columns.map(_ + "_R"):_*), $"common_field" === $"common_field_R")

另一个简单的解决方案就是这样做:

DataFrame

这两种解决方案都有效,我可以看到每种解决方案在某些情况下都很有用。我应该注意两者之间是否存在内部差异?

1 个答案:

答案 0 :(得分:29)

至少有两种不同的方法可以通过别名来解决这个问题:

df.as("df1").join(df.as("df2"), $"df1.foo" === $"df2.foo")

或使用基于名称的相等连接:

// Note that it will result in ambiguous column names
// so using aliases here could be a good idea as well.
// df.as("df1").join(df.as("df2"), Seq("foo"))

df.join(df, Seq("foo"))  

通常,列重命名虽然最丑,但却是所有版本中最安全的做法。有很多与列分辨率相关的错误(we found one on SO不久前),如果您使用原始表达式,解析器(HiveContext /标准SQLContext)之间的某些细节可能会有所不同。

我个人更喜欢使用别名,因为它们与惯用SQL的相似性以及在特定DataFrame对象范围之外使用的能力。

关于性能,除非您对接近实时的处理感兴趣,否则应该没有任何性能差异。所有这些都应该生成相同的执行计划。