我正在为2个数据格式编写一个联接查询。我必须在列上执行连接,该列在两个dataframes中具有相同的名称。我如何在查询中编写它?
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。对于此输出,dataframe将有ID, NAME, NAME, ACTUALNAME列。如何删除来自df2的额外NAME列。
这不像spark.sql("select * from table1 LEFT OUTER JOIN table2 ON table1.NAME = table2.NAME").drop(df2("NAME"))那样起作用
有更干净的方法吗?重命名df2列是我不想使用的最后一个选项。在我的场景中,创建SQL查询比数据访问更容易,因此查找只会激发SQL特定的答案。
发布于 2019-10-31 09:26:40
尝试一下,您可以使用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|
+---+----+----------+发布于 2019-10-31 11:51:28
这主要是一项学术练习,但您也可以通过打开Spark在引用标识符中解释正则表达式的能力(一种从Hive SQL继承来的能力),而不需要删除列。构建火花上下文时,需要将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的所有列,但NAME除外。任何有效的Java正则表达式都应该可以工作。
发布于 2019-10-31 09:23:31
如果没有将别名应用于dataframe,则在创建已连接的dataframe后将收到一个错误。对于两个名称相同的列,引用其中一个重复的命名列将返回一个错误,该错误本质上说它不知道您选择了哪一列(含糊不清)。在Server和其他语言中,SQL引擎不会让查询通过,或者会自动在字段名后面添加前缀或后缀。
https://stackoverflow.com/questions/58640143
复制相似问题