Spark SQL单语句双SELECT加UNION和Group by报错如何解决?
问题原因分析
- 报错的核心问题出在第一个
SELECT子句存在语法错误:
你在第一个查询中使用了SUM()聚合函数,但没有添加对应的GROUP BY CD_CLI子句。SQL规范要求,当查询同时返回非聚合列(此处为CD_CLI)和聚合函数时,所有非聚合列都必须出现在GROUP BY子句中,否则会触发你遇到的分组表达式为空的报错。 - 额外注意UNION的使用规范:
UNION要求上下两个查询返回的列数量、列顺序、对应列的数据类型必须完全匹配,最终返回的列名默认取第一个查询的列名。如果你的需求是把两个指标合并到同一行的同一个CD_CLI下,应该用JOIN而不是UNION。
修正方案
方案1:如果需要将两个查询结果上下堆叠合并(即UNION的原本作用
给第一个查询添加GROUP BY CD_CLI即可,同时建议统一第二列的列名避免后续使用混淆:
spark.sql('''SELECT CD_CLI, CASE WHEN SUM(in_lim_crt) > 0 THEN ROUND(SUM(SUM_VL_TTL_FAT)/SUM(in_lim_crt), 4) ELSE -99999999999 END AS VL_MED_FAT, '2017-01-31' as DT_MVTC FROM in_lim_fat WHERE DT_MVTC BETWEEN '2016-07-31' AND '2016-12-31' GROUP BY CD_CLI UNION SELECT CD_CLI, MAX(VL_RPTD_UTZO) AS VL_MED_FAT, '2017-01-31' AS DT_MVTC FROM vl_rptd_utzo WHERE DT_EXTC BETWEEN '2016-07-31' AND '2016-12-31' GROUP BY CD_CLI ''').createOrReplaceTempView('media_vl_fatura_2017_01_31')
方案2:如果需要每个CD_CLI同时展示两个统计指标
使用FULL JOIN关联两个子查询的结果,把两个指标放到同一行:
spark.sql(''' WITH t1 AS ( SELECT CD_CLI, CASE WHEN SUM(in_lim_crt) > 0 THEN ROUND(SUM(SUM_VL_TTL_FAT)/SUM(in_lim_crt), 4) ELSE -99999999999 END AS VL_MED_FAT, '2017-01-31' as DT_MVTC FROM in_lim_fat WHERE DT_MVTC BETWEEN '2016-07-31' AND '2016-12-31' GROUP BY CD_CLI ), t2 AS ( SELECT CD_CLI, MAX(VL_RPTD_UTZO) AS MAX_VL_RPTD_UTZO, '2017-01-31' AS DT_MVTC FROM vl_rptd_utzo WHERE DT_EXTC BETWEEN '2016-07-31' AND '2016-12-31' GROUP BY CD_CLI ) SELECT COALESCE(t1.CD_CLI, t2.CD_CLI) AS CD_CLI, t1.VL_MED_FAT, t2.MAX_VL_RPTD_UTZO, COALESCE(t1.DT_MVTC, t2.DT_MVTC) AS DT_MVTC FROM t1 FULL OUTER JOIN t2 ON t1.CD_CLI = t2.CD_CLI AND t1.DT_MVTC = t2.DT_MVTC ''').createOrReplaceTempView('media_vl_fatura_2017_01_31')
Spark SQL完全支持UNION和临时视图创建的写法,只要符合SQL语法规范即可正常运行。
内容的提问来源于stack exchange,提问作者Silvio sjsj
相关产品推荐
相关产品推荐

