Java Spark:如何在列的一部分上构建半加性度量或聚合和?

Java Spark:如何在列的一部分上构建半加性度量或聚合和?,java,apache-spark,apache-spark-sql,Java,Apache Spark,Apache Spark Sql,我试图在spark中重现我在传统BI中所做的一些分析。使用的技术术语是如何构建半加性度量,但如果我解释这意味着什么,可能会有所帮助 例如,假设我每天都有一份股票持有量清单。昨天我有100个,今天我有50个。这是一个半累加度量,因为你没有150。你有50个。所以你只想总结一下今天的情况。但是,像销售额这样的东西是完全相加的,比如说,你可以把全年的销售额加起来 所以问题是如何使用agg和sum构建一个半加性度量?我该如何编写agg语句来同时显示半加性和全加性度量?例如: val stocks = (

我试图在spark中重现我在传统BI中所做的一些分析。使用的技术术语是如何构建半加性度量,但如果我解释这意味着什么,可能会有所帮助

例如,假设我每天都有一份股票持有量清单。昨天我有100个,今天我有50个。这是一个半累加度量,因为你没有150。你有50个。所以你只想总结一下今天的情况。但是,像销售额这样的东西是完全相加的,比如说,你可以把全年的销售额加起来

所以问题是如何使用agg和sum构建一个半加性度量?我该如何编写agg语句来同时显示半加性和全加性度量?例如:

val stocks = (Seq(
             ("2019-05-01", 1, "FB", 1058.45, 100000),
             ("2019-05-01", 1, "NVDA", 40058.45, 150000),
             ("2019-05-03", 1, "FB", 8058.45, 80000),
             ("2019-05-04", 1, "FB", 11058.45, 75000),  // Latest FB entry for account 1 
             ("2019-05-05", 1, "NVDA", 50058.45, 125000),  // Latest NVDA entry for account 1
             ("2019-05-01", 2, "FB", 1058.45, 200000),
             ("2019-05-02", 2, "NVDA", 5058.45, 125000),
             ("2019-05-03", 2, "NVDA", 5058.45, 115000),
             ("2019-05-05", 2, "FB", 1058.45, 65000),   // latest FB entry for account 2
             ("2019-05-06", 2, "NVDA", 5058.45, 105000)  // latest NVDA entry for account 2
          ).toDF("date", "symbol", "account", "sale", "current_holdings"))

 stocks
     .groupBy( stocks.col("symbol") )
     .add( sum("earnings"), sum("current_holdings") )
     .show()
这将产生什么:

+------+---------+----------------+
|symbol|sale     |current_holdings|
+------+---------+----------------+
|    FB| 34291.80|        520000.0|
|  NDVA|105292.20|        525500.0|
+------+---------+----------------+
+------+---------+----------------+
|symbol|sale     |current_holdings|
+------+---------+----------------+
|    FB| 34291.80|          140000|
|  NDVA|105292.20|          230000|
+------+---------+----------------+
应产生:

+------+---------+----------------+
|symbol|sale     |current_holdings|
+------+---------+----------------+
|    FB| 34291.80|        520000.0|
|  NDVA|105292.20|        525500.0|
+------+---------+----------------+
+------+---------+----------------+
|symbol|sale     |current_holdings|
+------+---------+----------------+
|    FB| 34291.80|          140000|
|  NDVA|105292.20|          230000|
+------+---------+----------------+
在“预期”中,差异仅存在于“当前_控股”列中,该列将汇总所有账户的所有最新分录。因此,为FB添加最新条目时,您会得到:

FB = 75000 + 65000
NVDA = 125000 + 105000
我看过WindowFunctions,但除了分区中的特定索引外,我看不到如何指定求和的条件,如果说我需要对特定月份的所有内容求和,这将很困难。Spark是如何做到这一点的

附言: 请原谅这个奇怪的例子,我不得不把它改编成供公众观看

PSS:
我也很难做到这一点,因为每个帐户/符号的最新日期不符合可预测的边界。在我的具体情况下,我实际上试图总结出只属于给定时间段年、季度等最后一个月的情况。我希望这是一个更简单的情况,但我想充分探索半加法用例,所以我使问题变得困难。

PySpark解决方案可以修改为其等效的Scala代码

使用row_number对每个帐户的行进行编号,按日期的描述顺序使用符号,并对每组第一行的保留值求和

w=Window.partitionBy(stocks.account,stocks.symbol).orderBy(stocks.date.desc())
stocks = stocks.withColumn('rnum',row_number().over(w))
w1 = Window.partitionBy(stocks.symbol)
stocks = stocks.withColumn('sales',sum(stocks.sale).over(w1)).withColumn('holdings',sum(when(stocks.rnum==1,stocks.current_holdings).otherwise(0)).over(w1))
#Final selection
stocks.select(stocks.symbol,stocks.sales,stocks.holdings).distinct().show() 

你能更详细地解释一下逻辑吗?好的,我认为这应该有助于更清楚地说明如何求和这些值以匹配预期值。