Spark SQL Java添加具有不同行数的列

时间:2019-06-19 16:18:52

标签: java apache-spark-sql

SQL和Spark的新手,我试图在包含不同计数的数据集上添加一列。 数据集:

| col1 | col2 | 
|   A  |  B   |
|   C  |  D   |
|   A  |  B   |
|   A  |  B   |

所需结果:

| col1 | col2 | uniques |
|   A  |  B   |   3     |
|   C  |  D   |   1     |

我的Java代码:

return dataset.agg(countDistinct(col1,col2));

但是没有效果

1 个答案:

答案 0 :(得分:1)

区别不适用于此处。在计数之前,对每组中的不同 remove 重复项进行计数,因此“唯一性”列始终将仅包含一个。

要获得所需的结果,您需要执行基本的分组/聚合操作。以下是实现它的方法:

SparkSession spark = ...;

StructType schema = new StructType(new StructField[]{
    new StructField("col1", DataTypes.StringType, true, new MetadataBuilder().build()),
    new StructField("col2", DataTypes.StringType, true, new MetadataBuilder().build())
});

List<Row> rows = new ArrayList<>();
rows.add(RowFactory.create("A", "B"));
rows.add(RowFactory.create("C", "D"));
rows.add(RowFactory.create("A", "B"));
rows.add(RowFactory.create("A", "B"));

Dataset<Row> ds = spark.createDataFrame(rows, schema);
ds.createTempView("table");

// (1)
spark.sql("select col1, col2, count(*) as uniques from table group by col1, col2").show();

// (2)
ds.groupBy(ds.col("col1"), ds.col("col2")).count().show();

// (3)
ds.groupBy(ds.col("col1"), ds.col("col2"))
  .agg(functions.count(functions.lit(1)).alias("uniques") /*, functions.avg(...), functions.sum(...) */)
  .show();

第一个示例是所谓的“ Spark SQL”。

(2)和(3)的语法可能很难理解。我将尝试用非常基本的术语来解释它们。 groupBy(逻辑上)将数据分组为类似Map<GroupKey, List<Row>>的数据。 count将计数聚合函数应用于每个组(此函数的结果是新列),然后“扔掉” List<Row>。因此,在结果中,我们有一个表,该表由“ col1”,“ col2”(由于它们是分组键而被自动添加)和新列“ uniques”组成。

有时您需要同时应用多个聚合函数。第三个例子解决了这个问题。您可以在agg中列出多个功能。每个此类函数都会产生一个新列。