小言_互联网的博客

SparkSQL中两个decimal类型数据相除为null的问题

297人阅读  评论(0)

源表pdwqy_qxzh_piu字段类型:

如代码所示,在计算过程时,RFHL计算结果总是为null。
代码:

//读取数据
val data: DataFrame = spark.read.format("jdbc")
      .option("url", "jdbc:mysql://21.76.120.96:3306/us_app")
      .option("dbtable", "pdwqy_qxzh_piu")
      .option("user", "root")
      .option("password", "zhbr@1234")
      .load()
data.createTempView("PIU_Table")

val resultData = spark.sql(
      """
        |SELECT
        |               T1.TG_ID,
        |               date(T1.DATA_DATE) DATA_DATE,
        |               T1.I1,
        |               T1.I2,
        |               T1.I3,
        |               ROUND(AVG(T2.FZL), 4) PJFZL,
        |               ROUND(MAX(T2.FZL), 4) ZDFZL,
        |               ROUND(MIN(T2.FZL), 4) ZXFZL,
        |               case when MAX(T2.FZL) != 0 then round((AVG(T2.FZL)/MAX(T2.FZL))*100,4) else 0 end RFHL
        |          FROM PIU_Table T1 JOIN PIU_Table T2
        |         ON T1.TG_ID = T2.TG_ID
        |           and date(t1.data_date) = date(T2.data_date)
        |                  where t1.SJD='96'
        |         GROUP BY T1.I1,
        |                  T1.I2,
        |                  T1.I3,
        |                  T1.TG_ID,
        |                  date(T1.DATA_DATE)
      """.stripMargin)

//打印字段类型
resultData.printSchema()

//将数据保存到表
ConnOracleUtile.writeData(resultData,"pdwqy_qxzh_sbyxsj_copy")

通过打印字段类型字段类型,得知数据类型AVG(T2.FZL)和MAX(T2.FZL)均为decimal:

而计算完的结果,RFHL为null。也就是两个decimal类型的值相除的结果为null。

解决方法:
自定义一个求两个decimal类型数值相除的函数:

//自定义函数
spark.udf.register("chufa", (num1: java.math.BigDecimal ,num2: java.math.BigDecimal) => {
      (num1.toString.toDouble/num2.toString.toDouble)
 })

val resultData = spark.sql(
      """
        |SELECT
        |               T1.TG_ID,
        |               yearMonthDay(T1.DATA_DATE) DATA_DATE,
        |               T1.I1,
        |               T1.I2,
        |               T1.I3,
        |               ROUND(AVG(T2.FZL), 4) PJFZL,
        |               ROUND(MAX(T2.FZL), 4) ZDFZL,
        |               ROUND(MIN(T2.FZL), 4) ZXFZL,
        |               case when MAX(T2.FZL) != 0 then round(chufa(AVG(T2.FZL),MAX(T2.FZL))*100,4) else 0 end RFHL
        |          FROM PIU_Table T1 JOIN PIU_Table T2
        |         ON T1.TG_ID = T2.TG_ID
        |           and yearMonthDay(t1.data_date) = yearMonthDay(T2.data_date)
        |                  where t1.SJD='96'
        |         GROUP BY T1.I1,
        |                  T1.I2,
        |                  T1.I3,
        |                  T1.TG_ID,
        |                  yearMonthDay(T1.DATA_DATE)
      """.stripMargin)
resultData.printSchema()

//将数据保存到表
ConnOracleUtile.writeData(resultData,"pdwqy_qxzh_sbyxsj_copy")

这时目标表中RFHL字段就有了数据:

原因探究:

参考此文章https://issues.apache.org/jira/browse/SPARK-22036?jql=project%20%3D%20SPARK%20AND%20text%20~%20"BigDecimal"中对于SPARK-22036bug的描述:BigDecimal multiplication sometimes returns null

spark确实存在此版本bug,两个BigDecimal类型的数相乘,有时会返回null。
但是关于两个BigDecimal类型的数相除是否也存在这样的问题,本人暂时还没有找到相关的说明。
那可不可以这样猜想,a/b也可以看做是a*(1/b)呢,仅作为一种猜想吧。


转载:https://blog.csdn.net/weixin_44455388/article/details/100984844
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场