我想 sum
(也可以执行其他聚合函数)使用sparksql对数组列执行。
我有一张table
+-------+-------+---------------------------------+
|dept_id|dept_nm| emp_details|
+-------+-------+---------------------------------+
| 10|Finance| [100, 200, 300, 400, 500]|
| 20| IT| [10, 20, 50, 100]|
+-------+-------+---------------------------------+
我想把这个的值加起来 emp_details
列。
预期查询:
sqlContext.sql("select sum(emp_details) from mytable").show
预期结果
1500
180
我也应该能够对范围元素求和,比如:
sqlContext.sql("select sum(slice(emp_details,0,3)) from mytable").show
结果
600
80
当按预期对数组类型执行sum时,它显示sum预期参数是数值类型而不是数组类型。
我认为我们需要为此创建自定义项。但是怎么做呢?
我将面临任何与自定义项性能打击?除了udf之外还有其他解决方案吗?
6条答案
按热度按时间e7arh2l61#
rdd方法丢失了,所以让我添加它。
输出:
xpcnnkqh2#
因为spark 2.4你可以用
slice
功能:与数组求和
aggregate
:bwleehnv3#
这里有一个替代mtoto的答案而不使用
groupBy
(我真的不知道哪一个最快:udf,mtoto解决方案还是我的,欢迎评论)使用
UDF
,一般来说。有一个答案,你可能想读,这是一个很好的资源阅读自定义项。现在对于您的问题,您可以避免使用自定义项。我会用一个
Column
用scala逻辑生成的表达式。数据:
你需要一些诡计才能穿越
ArrayType
,您可以使用解决方案来发现各种问题(有关详细信息,请参阅底部的编辑)slice
零件)。这是我的建议,但你可能会发现更好。首先取最大长度然后使用它,当你有一个较短的数组时进行测试
结果:
我建议你看看
sumArray
去了解它在做什么。编辑:当然我只看了一半的问题了。。。但是,如果您想更改要求和的项,您可以看到使用此解决方案会变得很明显(即,您不需要切片函数),只需更改
(0 until maxLength)
使用所需的索引范围:dluptydi4#
Spark2.4.0
从spark2.4开始,sparksql支持高阶函数来操作复杂的数据结构,包括数组。
“现代”解决办法如下:
您可以在以下文章和视频中找到有关高阶函数的详细资料:
在ApacheSpark2.4中为复杂数据类型引入新的内置函数和高阶函数
在databricks上使用sql中的高阶函数处理嵌套数据
用herman van hovell(databricks)介绍spark-sql中的高阶函数
spark 2.3.2及更早版本
免责声明我不推荐这种方法(尽管它获得了最多的赞成票),因为sparksql执行的是反序列化
Dataset.map
. 该查询强制spark反序列化数据并将其加载到jvm(从由spark在jvm外部管理的内存区域)。这将不可避免地导致更频繁的gcs,从而使性能更差。一种解决办法是
Dataset
sparksql和scala的结合可以展示其强大功能的解决方案。我把切片部分留作练习,因为它同样简单。
mm5n2pyu5#
基于zero323令人敬畏的答案;如果您有一个长整数数组,即bigint,您需要将初始值从0更改为bigint(0),如第一段所述,以便
nwnhqdif6#
可能使用的方法
explode()
在你的Array
列,从而按唯一键聚合输出。例如:要仅选择数组中的特定值,我们可以使用链接问题的答案,并稍加修改即可应用:
数据: