Spark SQL中DataFrame三列数值求和返回NULL值的问题咨询
问题根因
核心错误是第三步求和查询读取的是原始表raw_population,完全没有用到第二步做了空值替换的处理结果,之前写的COALESCE逻辑根本没有在求和计算里生效:
- 第二步带
COALESCE的查询仅生成了独立的DataFrame对象df_raw_population_pi,你既没有把清洗后的结果写回原表raw_population,也没有把这个DataFrame注册为临时视图供后续SQL调用。 - 执行第三步求和SQL时,
FROM raw_population读取的始终是未做任何清洗的原始数据,这张表里percentage_2020、percentage_2021对应AD、AM等行的原始值就是NULL。按照SQL标准运算规则,算术表达式中只要有任意一个操作数为NULL,整个表达式返回结果就是NULL,这就是你看到有效值加0.00得到NULL的原因——你看到的0.00是df_raw_population_pi里的清洗结果,不是原表raw_population里的存储值,原表对应位置还是NULL。
修复方案
选任意一种即可:
方案1:在求和SQL中直接补全清洗逻辑
不依赖之前的DataFrame,直接把正则替换、类型转换、空值替换的逻辑写在求和语句里:
SELECT country_code, age_group, ( COALESCE(cast(regexp_replace(percentage_2019, '[a-z]', '') AS decimal(4,2)), 0) + COALESCE(cast(regexp_replace(percentage_2020, '[a-z]', '') AS decimal(4,2)), 0) + COALESCE(cast(regexp_replace(percentage_2021, '[a-z]', '') AS decimal(4,2)), 0) ) AS sum_percentage_years FROM raw_population WHERE length(country_code) = 2
方案2:注册清洗后临时视图复用逻辑
先把清洗完成的DataFrame注册为临时视图,后续所有查询直接读清洗后的视图,不用重复写转换逻辑:
# 执行清洗逻辑,过滤符合长度要求的country_code df_raw_population_pi = spark.sql(""" SELECT country_code, age_group, COALESCE(cast(regexp_replace(percentage_2019, '[a-z]', '') AS decimal(4,2)),0) AS percentage_2019, COALESCE(cast(regexp_replace(percentage_2020, '[a-z]', '') AS decimal(4,2)),0) AS percentage_2020, COALESCE(cast(regexp_replace(percentage_2021, '[a-z]', '') AS decimal(4,2)),0) AS percentage_2021 FROM raw_population WHERE length(country_code) = 2 """) # 注册临时视图,供后续SQL查询 df_raw_population_pi.createOrReplaceTempView("cleaned_population") # 求和时直接读取清洗后的视图 df_raw_population_pivot = spark.sql(""" SELECT country_code, age_group, percentage_2019 + percentage_2020 + percentage_2021 AS sum_percentage_years FROM cleaned_population """) df_raw_population_pivot.head(10)
补充说明:Spark的DataFrame是惰性执行的,仅定义转换逻辑不会修改原始源表的数据,也不会自动让后续SQL感知到你之前定义的转换规则,必须将处理后的结果注册为临时视图/表、或者写入持久化存储,后续查询才能用到清洗后的数据。
内容的提问来源于stack exchange,提问作者Abhi96
相关产品推荐
相关产品推荐

