我正在为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具体答案
答案 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正则表达式都应该起作用。