使用ApacheSpark,使用Java将每个组的前2行变平
给出以下输入表:使用ApacheSpark,使用Java将每个组的前2行变平,java,mysql,apache-spark,hive,Java,Mysql,Apache Spark,Hive,给出以下输入表: +----+------------+----------+ | id | shop | purchases| +----+------------+----------+ | 1 | 01 | 20 | | 1 | 02 | 31 | | 2 | 03 | 5 | | 1 | 03 | 3 | +----+------------+-----
+----+------------+----------+
| id | shop | purchases|
+----+------------+----------+
| 1 | 01 | 20 |
| 1 | 02 | 31 |
| 2 | 03 | 5 |
| 1 | 03 | 3 |
+----+------------+----------+
我想根据id和购买情况分组,获得前2家顶级店铺,如下所示:
+----+-------+------+
| id | top_1 | top_2|
+----+-------+------+
| 1 | 02 | 01 |
| 2 | 03 | |
+----+-------+------+
我使用的是ApacheSpark2.0.1,第一个表是数据集上其他查询和联接的结果。我可以用传统的java在数据集上进行迭代,但我希望有另一种方法使用数据集功能。
我的第一次尝试是:
//dataset is already ordered by id, purchases desc
...
Dataset<Row> ds = dataset.repartition(new Column("id"));
ds.foreachPartition(new ForeachPartitionFunction<Row>() {
@Override
public void call(Iterator<Row> itrtr) throws Exception {
int counter = 0;
while (itrtr.hasNext()) {
Row row = itrtr.next();
if(counter < 2)
//save it into another Dataset
counter ++;
}
}
});
//数据集已按id订购,购买说明
...
Dataset ds=Dataset.repartition(新列(“id”);
ds.foreachPartition(新的ForeachPartitionFunction(){
@凌驾
公共无效调用(迭代器itrtr)引发异常{
int计数器=0;
while(itrtr.hasNext()){
行=itrtr.next();
如果(计数器<2)
//将其保存到另一个数据集中
计数器++;
}
}
});
但后来我对如何将其保存到另一个数据集中感到困惑。最后,我的目标是将结果保存到MySQL表中。使用窗口函数和pivot,您可以定义一个窗口:
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions.{col, first, row_number}
val w = Window.partitionBy(col("id")).orderBy(col("purchases").desc)
添加行号
并过滤顶部两行:
val dataset = Seq(
(1, "01", 20), (1, "02", 31), (2, "03", 5), (1, "03", 3)
).toDF("id", "shop", "purchases")
val topTwo = dataset.withColumn("top", row_number.over(w)).where(col("top") <= 2)
结果是:
+---+---+----+
|id | 1 | 2|
+---+---+----+
| 1| 02| 01|
|2 | 03 |空|
+---+---+----+
我将把把语法转换成Java作为海报的练习(不包括import static
函数,其余的应该差不多相同)
topTwo.groupBy(col("id")).pivot("top", Seq(1, 2)).agg(first("shop"))