使用SparkSQL时使用SQL语句中的COLLECT_SET和后期处理需要注意问题

在使用SparkSQL的SQL语句进行聚合后拼接时,需要使用CONCAT_WS进行多字段拼接,再使用COLLECT_SET进行收集,返回一个Array数组的集合。

如:

 val imo_type_sql =
      """
        |SELECT IMO, MMSI, COLLECT_SET(CONCAT_WS("~",ShipType, count)) as type_count
        |FROM agg_table
        |GROUP BY IMO, MMSI
      """.stripMargin

    val imo_type_df: DataFrame = session.sql(imo_type_sql)
    imo_type_df.createOrReplaceTempView("all_type_table")

后面进行业务处理,需要在这个数组中选取count次数最多的一个ShipType,故选用Spark的自定义UDF方式进行实现。

session.udf.register("filterType", (arr:Seq[String]) =>{
      val map: Map[String, Long] = arr.map {
        case type_count_str: String => {
          val type_count = type_count_str.split("~")
          val shiptype = type_count(0)
          var count = 0L
          try {
            count = type_count(1).toLong
          } catch {
            case e: Exception => count = 0L
          }
          (shiptype, count)
        }
      }.sortBy(-_._2).toMap
      map.head.toString()
    })

注: 在进行自定义UDF时,不能使用输入类型是Array,如:

 session.udf.register("filterType", (arr:Array[String]) =>{}

使用Array时,会报如下异常:

Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to [Ljava.lang.String;

这是是选用Array的父类,将Array改成Seq就可以传入Array类型,原因是此Array非Scala中的原生Array,而是封装了一下的Array,详细说明:

So it looks like the ArrayType on Dataframe "idDF" is really a WrappedArray and not an Array - So the function call to "filterMapKeysWithSet" failed as it expected an Array but got a WrappedArray/ Seq instead (which doesn't implicitly convert to Array in Scala 2.8 and above).

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R_记忆犹新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值