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

源表pdwqy_qxzh_piu字段类型:
SparkSQL中两个decimal类型数据相除(相乘)为null的问题_第1张图片
如代码所示,在计算过程时,RFHL计算结果总是为null。
代码:

//读取数据
val data: DataFrame = spark.read.format("jdbc")
      .option("url", "jdbc:mysql://21.76.120.XX:3306/us_app")
      .option("dbtable", "pdwqy_qxzh_piu")
      .option("user", "root")
      .option("password", "XXX")
      .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:
SparkSQL中两个decimal类型数据相除(相乘)为null的问题_第2张图片
而计算完的结果,RFHL为null。也就是两个decimal类型的值相除的结果为null。
SparkSQL中两个decimal类型数据相除(相乘)为null的问题_第3张图片
解决方法:
自定义一个求两个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字段就有了数据:
SparkSQL中两个decimal类型数据相除(相乘)为null的问题_第4张图片
原因探究:

参考此文章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)呢,仅作为一种猜想吧。
SparkSQL中两个decimal类型数据相除(相乘)为null的问题_第5张图片

你可能感兴趣的:(SparkSQL,decimal,mysql,Spark)