Java 如何在从数据集中选择列的不同值时保持数据的顺序

Java 如何在从数据集中选择列的不同值时保持数据的顺序,java,sql,apache-spark,apache-spark-sql,Java,Sql,Apache Spark,Apache Spark Sql,我有一个如下的数据集 +------+------+---------------+ | col1 | col2 | sum(costs) | +------+------+---------------+ | 1 | a | 3555204326.27 | | 4 | b | 22273491.72 | | 5 | c | 219175.00 | | 3 | a | 219175.00 | | 2 | c |

我有一个如下的数据集

+------+------+---------------+
| col1 | col2 |  sum(costs)   |
+------+------+---------------+
|    1 | a    | 3555204326.27 |
|    4 | b    | 22273491.72   |
|    5 | c    | 219175.00     |
|    3 | a    | 219175.00     |
|    2 | c    | 75341433.37   |
+------+------+---------------+
我需要选择col1的不同值,结果数据集的顺序应该是1、4、5、3、2(这些值在初始数据集中的可用顺序)。但秩序正在改变。有没有办法保持与初始数据集相同的顺序。Spark/SQL中的任何建议都可以

该数据集可通过spark中的以下顺序获得

df = sqlCtx.createDataFrame(
  [(1, a, 355.27), (4, b, 222.98), (5, c, 275.00), (3, a, 25.00),
   (2, c, 753.37)], ('Col1', 'col2', 'cost'));

您可以向数据库中添加一个索引列,然后在SQL请求中按id进行排序。我认为您需要重新格式化查询,并使用group BY而不是distinct,如下面的回答所示。您可以添加另一列,其中包含每行的索引,然后在“distinct”之后对该列进行排序。以下是一个例子:

import org.apache.spark.sql.functions._

val df = Seq(1, 4, 4, 5, 2)
  .toDF("a")
  .withColumn("id", monotonically_increasing_id())
df.show()
// +---+---+
// |  a| id|
// +---+---+
// |  1|  0|
// |  4|  1|
// |  4|  2|
// |  5|  3|
// |  2|  4|
// +---+---+

df.dropDuplicates("a").sort("id").show()
// +---+---+
// |  a| id|
// +---+---+
// |  1|  0|
// |  4|  1|
// |  5|  3|
// |  2|  4|
// +---+---+

请注意,要在1个特定列上执行distinct操作,可以使用
dropDuplicates
,如果要控制在重复情况下要采取的行,请使用
groupBy
,,假设您尝试在
col2
中远程复制(因为
col1
中没有),以便最终结果为:

+----+----+---------------+
|col1|col2|            sum|
+----+----+---------------+
|   1|   a|3.55520432627E9|
|   4|   b|  2.227349172E7|
|   5|   c|       219175.0|
+----+----+---------------+

您可以添加一个索引列,如:

df = df.withColumn("__idx", monotonically_increasing_id());
然后执行所有需要的转换,然后将其删除,如:

df = df.dropDuplicates("col2").orderBy("__idx").drop("__idx");
这意味着你要:

步骤1:加载数据和内容:

+----+----+---------------+
|col1|col2|            sum|
+----+----+---------------+
|   1|   a|3.55520432627E9|
|   4|   b|  2.227349172E7|
|   5|   c|       219175.0|
|   3|   a|       219175.0|
|   2|   c|  7.534143337E7|
+----+----+---------------+
步骤2:添加索引:

+----+----+---------------+-----+
|col1|col2|            sum|__idx|
+----+----+---------------+-----+
|   1|   a|3.55520432627E9|    0|
|   4|   b|  2.227349172E7|    1|
|   5|   c|       219175.0|    2|
|   3|   a|       219175.0|    3|
|   2|   c|  7.534143337E7|    4|
+----+----+---------------+-----+
步骤3:转换(此处删除
col2
中的DUP)并删除
\uu idx
列:

+----+----+---------------+
|col1|col2|            sum|
+----+----+---------------+
|   1|   a|3.55520432627E9|
|   4|   b|  2.227349172E7|
|   5|   c|       219175.0|
+----+----+---------------+
Java代码可以是:

package net.jgp.books.spark.ch12.lab990_others;

import static org.apache.spark.sql.functions.monotonically_increasing_id;

import java.util.ArrayList;
import java.util.List;

import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

/**
 * Keeping the order of rows during transformations.
 * 
 * @author jgp
 */
public class KeepingOrderApp {

  /**
   * main() is your entry point to the application.
   * 
   * @param args
   */
  public static void main(String[] args) {
    KeepingOrderApp app = new KeepingOrderApp();
    app.start();
  }

  /**
   * The processing code.
   */
  private void start() {
    // Creates a session on a local master
    SparkSession spark = SparkSession.builder()
        .appName("Splitting a dataframe to collect it")
        .master("local")
        .getOrCreate();

    Dataset<Row> df = createDataframe(spark);
    df.show();

    df = df.withColumn("__idx", monotonically_increasing_id());
    df.show();

    df = df.dropDuplicates("col2").orderBy("__idx").drop("__idx");
    df.show();
  }

  private static Dataset<Row> createDataframe(SparkSession spark) {
    StructType schema = DataTypes.createStructType(new StructField[] {
        DataTypes.createStructField(
            "col1",
            DataTypes.IntegerType,
            false),
        DataTypes.createStructField(
            "col2",
            DataTypes.StringType,
            false),
        DataTypes.createStructField(
            "sum",
            DataTypes.DoubleType,
            false) });

    List<Row> rows = new ArrayList<>();
    rows.add(RowFactory.create(1, "a", 3555204326.27));
    rows.add(RowFactory.create(4, "b", 22273491.72));
    rows.add(RowFactory.create(5, "c", 219175.0));
    rows.add(RowFactory.create(3, "a", 219175.0));
    rows.add(RowFactory.create(2, "c", 75341433.37));

    return spark.createDataFrame(rows, schema);
  }
}
package net.jgp.books.spark.ch12.lab990_其他;
导入静态org.apache.spark.sql.functions.monotional\u递增\u id;
导入java.util.ArrayList;
导入java.util.List;
导入org.apache.spark.sql.Dataset;
导入org.apache.spark.sql.Row;
导入org.apache.spark.sql.RowFactory;
导入org.apache.spark.sql.SparkSession;
导入org.apache.spark.sql.types.DataTypes;
导入org.apache.spark.sql.types.StructField;
导入org.apache.spark.sql.types.StructType;
/**
*在转换期间保持行的顺序。
* 
*@author jgp
*/
公共类KeepingOrderApp{
/**
*main()是应用程序的入口点。
* 
*@param args
*/
公共静态void main(字符串[]args){
KeepingOrderApp=新建KeepingOrderApp();
app.start();
}
/**
*处理代码。
*/
私有void start(){
//在本地主机上创建会话
SparkSession spark=SparkSession.builder()
.appName(“拆分数据帧以收集它”)
.master(“本地”)
.getOrCreate();
数据集df=createDataframe(spark);
df.show();
df=df.withColumn(“\uuuidx”,单调递增的\uid());
df.show();
df=df.dropDuplicates(“col2”).orderBy(“\uuuidx”).drop(“\uuuidx”);
df.show();
}
专用静态数据集createDataframe(SparkSession spark){
StructType架构=数据类型。createStructType(新的StructField[]{
DataTypes.createStructField(
“col1”,
DataTypes.IntegerType,
假),,
DataTypes.createStructField(
“col2”,
DataTypes.StringType,
假),,
DataTypes.createStructField(
“总和”,
DataTypes.DoubleType,
假)});
列表行=新建ArrayList();
添加(RowFactory.create(1,“a”,3555204326.27));
添加(RowFactory.create(4,“b”,22273491.72));
添加(RowFactory.create(5,“c”,219175.0));
添加(RowFactory.create(3,“a”,219175.0));
添加(RowFactory.create(2,“c”,75341433.37));
返回spark.createDataFrame(行,模式);
}
}

如果数据来源是不可变的,以及您使用的Spark版本是什么,您可以在问题中添加数据来源(CSV、数据库)吗。。。