连接数据集并重命名一列

时间:2019-02-17 19:26:49

标签: java apache-spark apache-spark-sql apache-spark-dataset

我知道如何做到这一点,但是我想(或者至少希望如此)有一种更简单,更少样板的方法来完成该任务。

场景:

Employee
+-------+---+------------+
|   NAME|AGE|COMPANY_CODE|
+-------+---+------------+
|   John| 41|           1|
|   Mary| 34|           1|
|  Chris| 32|           2|
|Phillip| 22|           2|
|   Tony| 44|           1|
+-------+---+------------+

Company
+----+---------+
|CODE|     NAME|
+----+---------+
|   1|Company-1|
|   2|Company-2|
|   3|Company-3|
+----+---------+

我的目标是通过 employee.company_code 和company_code 联接两个表,并将employee.name显示为 NAME ,employee.age显示为 AGE 和公司名称为 COMPANY_NAME (这是技巧部分)

// company columns
final Column companyCode = companyDataSet.col("CODE");

// employee columns
final Column employeeCompanyCode = employeeDataSet.col("COMPANY_CODE");

Dataset<Row> join = employeeDataSet.join(companyDataSet, employeeCompanyCode.equalTo(companyCode));

join = join.drop(companyCode).drop(employeeCompanyCode);

打印 join 数据框,现在我们得到:

+-------+---+---------+
|   NAME|AGE|     NAME|
+-------+---+---------+
|   John| 41|Company-1|
|   Mary| 34|Company-1|
|  Chris| 32|Company-2|
|Phillip| 22|Company-2|
|   Tony| 44|Company-1|
+-------+---+---------+

我不能使用withColumnRenamed方法( join.withColumnRenamed(“ NAME”,“ COMPANY_NAME” ),因为我有两列称为NAME,并且这两列都将被重命名

我发现这样做的唯一方法是定义要显示的所有列,将所有列传递给选择数据集方法,然后根据需要重命名列:

final Column companyName = companyDataSet.col("NAME");
final Column employeeName = employeeDataSet.col("NAME");
final Column employeeAge = employeeDataSet.col("AGE");

join = join.select(employeeName, employeeAge, companyName.alias("COMPANY_NAME"));

+-------+---+------------+
|   NAME|AGE|COMPANY_NAME|
+-------+---+------------+
|   John| 41|   Company-1|
|   Mary| 34|   Company-1|
|  Chris| 32|   Company-2|
|Phillip| 22|   Company-2|
|   Tony| 44|   Company-1|
+-------+---+------------+

在这种特定情况下,定义我要选择的所有列并不是一件大事,因为它们只是少数列,但可以想象在具有成堆的列的表中。由于一次可悲的列重命名而定义了很多列,这太痛苦了。

有什么办法可以避免这种情况吗?

3 个答案:

答案 0 :(得分:0)

您应该能够:

join = join.withColumnRenamed(companyDataSet.col("NAME"), "COMPANY_NAME")

能解决您的问题吗?

答案 1 :(得分:0)

一种方法是将它们注册为临时表并编写SQL?

employee.createOrReplaceTempView(emp)
company.createOrReplaceTempView(comp)

spark.sql("select t1.Name as Name, t1.Age as Age, t2.Name as Company_Name
        from 
        emp t1 join comp t2
        on
        t1.id = t2.id")

答案 2 :(得分:0)

我找到了一个简单的解决方案,没有我认为的数据集那么优雅。withColumnRenamed接受Column作为第一个参数,但是它比包含所有列更好,因为一个列重命名。

只需先从companyDataSet重命名NAME列,然后再加入employeeDataSet:

companyDataSet = companyDataSet.withColumnRenamed("NAME", "COMPANY_NAME");