基于多条件的Spark SQL求和实现及Spark DataFrame统计需求
基于Spark DataFrame实现多条件求和操作
先把你的示例数据补全下方便演示:
+----+------------+------+--------+-------+---------+ | id | date | type | player | level | stage | +----+------------+------+--------+-------+---------+ | 1 | 2018-03-26 | XXX | John | 4 | stage_2 | | 2 | 2018-03-26 | YYY | Adam | 1 | stage_1 | | 3 | 2018-03-26 | ZZZ | Sarah | 6 | stage_3 | | 4 | 2018-03-26 | XXX | Bruce | 12 | stage_2 | | 5 | 2018-03-26 | YYY | Sarah | 6 | stage_1 | | 6 | 2018-03-26 | XXX | John | 8 | stage_3 | +----+------------+------+--------+-------+---------+
下面给你两种常用的实现方式,你可以根据自己的习惯选择:
方式一:使用Spark SQL语法
首先得把DataFrame注册成临时视图,之后就能用熟悉的SQL语句实现多条件求和了:
1. 筛选多条件后单列求和
比如要统计date='2018-03-26'且type='XXX'的所有level总和:
// 注册临时视图 df.createOrReplaceTempView("game_data") // 执行SQL求和 val sumResult = spark.sql("SELECT SUM(level) AS total_level FROM game_data WHERE date = '2018-03-26' AND type = 'XXX'") sumResult.show()
执行后会得到结果:total_level为24(4+12+8)
2. 多条件分组求和(一次计算多个结果)
如果想同时统计不同条件下的总和,比如分别计算type='XXX'和type='YYY'且stage='stage_1'的level总和,可以用CASE WHEN:
SELECT SUM(CASE WHEN type = 'XXX' THEN level ELSE 0 END) AS sum_xxx_level, SUM(CASE WHEN type = 'YYY' AND stage = 'stage_1' THEN level ELSE 0 END) AS sum_yyy_stage1_level FROM game_data WHERE date = '2018-03-26'
这个SQL会同时输出两个结果:sum_xxx_level=24,sum_yyy_stage1_level=7(1+6)
方式二:使用DataFrame API(无SQL写法)
如果你更习惯用DataFrame的链式调用,也可以这样写:
1. 先过滤多条件再求和
import org.apache.spark.sql.functions.sum val sumResult = df .filter($"date" === "2018-03-26" && $"type" === "XXX") .agg(sum($"level").alias("total_level")) sumResult.show()
2. 多条件聚合(一次计算多个求和结果)
import org.apache.spark.sql.functions.{sum, when} val multiSumResult = df .filter($"date" === "2018-03-26") .agg( sum(when($"type" === "XXX", $"level").otherwise(0)).alias("sum_xxx_level"), sum(when($"type" === "YYY" && $"stage" === "stage_1", $"level").otherwise(0)).alias("sum_yyy_stage1_level") ) multiSumResult.show()
这个和前面SQL的CASE WHEN效果完全一致。
小提醒:
- 如果你的数据里有null值,可以在过滤条件里加上
isNotNull避免计算错误,比如filter($"level".isNotNull && ...) - 如果
date字段是日期类型而非字符串,记得用日期字面量格式,比如date = date'2018-03-26'
内容的提问来源于stack exchange,提问作者Am1rr3zA
相关产品推荐
相关产品推荐

