Spark DataFrame和HiveSQL - 删除列不起作用?

时间:2016-09-08 14:04:52

标签: java apache-spark dataframe hive

我有以下代码:

SparkConf sparkConf = new SparkConf();
JavaSparkContext ctx = new JavaSparkContext(sparkConf);
HiveContext sqlContext = new HiveContext(ctx.sc());

DataFrame df1 = sqlContext.read().json("../smthng/*.json");
DataFrame df2 = sqlContext.read().json("../else/*.json");

df1.registerTempTable("df1");
df2.registerTempTable("df2");

DataFrame df= sqlContext.sql("SELECT * " +
                             "FROM df1 " +
                             "LEFT OUTER JOIN df2 ON df1.id = df2.id " +
                             "WHERE df1.id IS NULL").drop("df1.id");

在这里,我尝试进行外部联接,然后删除其中一个id列。显然,联接会保留两个列,当我尝试进一步使用它时,它无法决定使用哪一个(我得到的错误如Reference 'id' is ambiguous, could be: id#59, id#376.;)。这就是我尝试删除其中一列的原因,但即使我使用....drop("df1.id");,它也无法正常工作。我有什么想法可以删除其中一个id列吗? 谢谢!

3 个答案:

答案 0 :(得分:2)

没有专栏" df1.id"在由连接查询创建的DF中,因此drop不起作用。考虑在DF之后返回查询。

+---+----+-----+----+
| id|name|email|  id|
+---+----+-----+----+
|  2| xxx| null|null|
|  3| zzz| null|null|
+---+----+-----+----+ 

如果你打电话给df.printSchema(),你会得到

root
|-- id: integer (nullable = false)
|-- name: string (nullable = true)
|-- email: string (nullable = true)
|-- id: integer (nullable = true)

所以如果你打电话给drop(" id")。它会掉落" id"列并将返回

+----+-----+
|name|email|
+----+-----+
| xxx| null|
| zzz| null|
+----+-----+

如果你想拥有一个" id"最终DF中的列然后将您的查询更改为如下所示

DataFrame df = sqlContext.sql("SELECT df1.id, df1.name, df2.email " +
            "FROM df1 " +
            "LEFT OUTER JOIN df2 ON df1.id = df2.id " 
            +"WHERE df1.id IS NULL");

它会返回

+---+----+-----+
| id|name|email|
+---+----+-----+
|  2| xxx| null|
|  3| zzz| null|
+---+----+-----+

Spark DF API提供类似"别名"的API。或" withColumnRename"处理DF中的重复列。另请参阅帖子Spark Dataframe distinguish columns with duplicated name

答案 1 :(得分:0)

在sql中使用列名,并使用别名 -

DataFrame df= sqlContext.sql("SELECT Column1 as col1,Column2 as col2...ColumnN as colN" +
                             "FROM df1 " +
                             "LEFT OUTER JOIN df2 ON df1.id = df2.id " +
                             "WHERE df1.id IS NULL").drop("df1.id");

希望这种方法不会给出像“模棱两可”这样的错误信息

答案 2 :(得分:0)

好的,我通过使用这样的连接解决了这个问题:

DataFrame df = df1.join(df2, df1.col("id").equalTo(df2.col("customer_id")), "left")
            .select("*").where(df1.col("id").isNotNull())
            .drop(df1.col("id"));