Spark SQL QUERY在相同列名称上联接

时间:2019-10-31 09:22:17

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

我正在为2个数据帧编写联接查询。我必须在两个数据帧中具有相同名称的列上执行连接。如何在查询中编写它?

var df1 = Seq((1,"har"),(2,"ron"),(3,"fred")).toDF("ID", "NAME")
var df2 = Seq(("har", "HARRY"),("ron", "RONALD")).toDF("NAME", "ACTUALNAME")
df1.createOrReplaceTempView("table1")
df2.createOrReplaceTempView("table2")

我知道我们可以做df3 = df1.join(df2, Seq("NAME")),其中NAME是通用列。在这种情况下,df3只有ID, NAME, ACTUALNAME

如果我们通过SQL进行操作,则查询将为select * from table1 LEFT OUTER JOIN table2 ON table1.NAME = table2.NAME。对于此输出数据帧将具有ID, NAME, NAME, ACTUALNAME列。如何删除来自NAME的额外df2列。

spark.sql("select * from table1 LEFT OUTER JOIN table2 ON table1.NAME = table2.NAME").drop(df2("NAME"))

效果不佳

是否有一种更清洁的方法?重命名df2列是我不想使用的最后一个选项。我有这样一种情况,即创建SQL查询比使用数据帧更容易,因此只寻找 SPARK SQL具体答案

4 个答案:

答案 0 :(得分:2)

尝试此操作,您可以使用col()引用列

scala> spark.sql("select * from table1 LEFT OUTER JOIN table2 ON table1.NAME = table2.NAME").drop(col("table2.NAME")).show()
+---+----+----------+
| ID|NAME|ACTUALNAME|
+---+----+----------+
|  1| har|     HARRY|
|  2| ron|    RONALD|
|  3|fred|      null|
+---+----+----------+

答案 1 :(得分:0)

如果不对数据框应用别名,则在创建联接的数据框后会收到错误消息。如果两个列的名称相同,则引用重复的命名列之一将返回错误,该错误实质上表明它不知道选择了哪一个(歧义)。在SQL Server和其他语言中,SQL引擎不会通过该查询,否则会自动在该字段名称后添加前缀或后缀。

答案 2 :(得分:0)

我们可以在sql查询中选择必填字段,如下所示

spark.sql("select A.ID,A.NAME,B.ACTUALNAME from table1 A LEFT OUTER JOIN table2 B ON table1.NAME = table2.NAME").show()

答案 3 :(得分:0)

这主要是一项学术练习,但是您也可以通过打开Spark SQL来解释带引号的标识符中的正则表达式的功能而无需删除列,这是从Hive SQL继承的功能。在构建Spark上下文时,需要将success: boolean设置为spark.sql.parser.quotedRegexColumnNames

true

这里

$ spark-shell --master "local[*]" --conf spark.sql.parser.quotedRegexColumnNames=true
...
scala> spark.sql("select table1.*, table2.`^(?!NAME$).*$` from table1 LEFT OUTER JOIN table2 ON table1.NAME = table2.NAME").show()
+---+----+----------+
| ID|NAME|ACTUALNAME|
+---+----+----------+
|  1| har|     HARRY|
|  2| ron|    RONALD|
|  3|fred|      null|
+---+----+----------+

解析为table2.`^(?!NAME$).*$` 之外的所有table2列。任何有效的Java正则表达式都应该起作用。