加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何对数组列的元素进行切片和求和?

发布时间:2020-12-16 18:26:30 所属栏目:安全 来源:网络整理
导读:我想使用SparkSQL对数组列求和(或执行其他聚合函数). 我有一张桌子 +-------+-------+---------------------------------+|dept_id|dept_nm| emp_details|+-------+-------+---------------------------------+| 10|Finance| [100,200,300,400,500]|| 20| IT
我想使用SparkSQL对数组列求和(或执行其他聚合函数).

我有一张桌子

+-------+-------+---------------------------------+
|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,3)) from mytable").show

结果

600
80

当对数组类型进行求和时,它表示sum预期参数为数字类型而不是数组类型.

我认为我们需要为此创建UDF.但怎么样?

我是否会面临使用UDF的任何性能命中?
除了UDF之外还有其他解决方案吗?

解决方法

Spark 2.4.0

从Spark 2.4开始,Spark SQL支持用于处理复杂数据结构(包括数组)的高阶函数.

“现代”解决方案如下:

scala> input.show(false)
+-------+-------+-------------------------+
|dept_id|dept_nm|emp_details              |
+-------+-------+-------------------------+
|10     |Finance|[100,500]|
|20     |IT     |[10,100]        |
+-------+-------+-------------------------+

input.createOrReplaceTempView("mytable")

val sqlText = "select dept_id,dept_nm,aggregate(emp_details,(value,acc) -> value + acc) as sum from mytable"
scala> sql(sqlText).show
+-------+-------+----+
|dept_id|dept_nm| sum|
+-------+-------+----+
|     10|Finance|1500|
|     20|     IT| 180|
+-------+-------+----+

您可以在以下文章和视频中找到关于高阶函数的好读物:

> Introducing New Built-in and Higher-Order Functions for Complex Data Types in Apache Spark 2.4
> Working with Nested Data Using Higher Order Functions in SQL on Databricks
> An Introduction to Higher Order Functions in Spark SQL with Herman van Hovell (Databricks)

Spark 2.3.2及更早版本

免责声明我不推荐这种方法(即使它得到了最多的赞成),因为Spark SQL执行数据集.map的反序列化.该查询强制Spark反序列化数据并将其加载到JVM(从JVM外部的Spark管理的内存区域).这将不可避免地导致更频繁的GC,从而使性能变差.

一种解决方案是使用数据集解决方案,其中Spark SQL和Scala的组合可以显示其功能.

scala> val inventory = Seq(
     |   (10,"Finance",Seq(100,500)),|   (20,"IT",Seq(10,100))).toDF("dept_id","dept_nm","emp_details")
inventory: org.apache.spark.sql.DataFrame = [dept_id: int,dept_nm: string ... 1 more field]

// I'm too lazy today for a case class
scala> inventory.as[(Long,String,Seq[Int])].
  map { case (deptId,deptName,details) => (deptId,details.sum) }.
  toDF("dept_id","sum").
  show
+-------+-------+----+
|dept_id|dept_nm| sum|
+-------+-------+----+
|     10|Finance|1500|
|     20|     IT| 180|
+-------+-------+----+

我将切片部分作为练习,因为它同样简单.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读