Azure Databricks中Group by查询因计算字段导致结果异常问题
Azure Databricks中LAST(AGE)与COUNT(DISTINCT DATE)共存时结果异常的原因及解决方法
问题原因
- 你子查询里的
ORDER BY BRAND, CUSTOMER, DATE完全没起作用。SQL标准明确规定:不带LIMIT的子查询ORDER BY是无效语法,Databricks的查询优化器会直接忽略这个排序逻辑。 - 只查询
LAST(AGE)时,执行计划可能碰巧让数据保持了某种顺序,导致结果正确,但这是偶然情况,不是可靠的既定行为。 - 一旦加入
COUNT(DISTINCT DATE),查询执行计划会彻底改变——为了完成去重计数,数据会被重新分区、洗牌,原有的顺序被完全打乱,LAST(AGE)就会随机取分组内的某条AGE值,自然出现错误结果。
解决方法
不要依赖子查询排序来配合LAST函数,改用窗口函数明确锁定每个分组内最新DATE对应的AGE,同时单独计算去重日期数。推荐两种稳定的写法:
方法一:先标记最新记录,再聚合统计
WITH ranked_data AS ( SELECT YEAR, MONTH, BRAND, CUSTOMER, AGE, DATE, -- 按DATE倒序排名,每个分组里最新的DATE排第1 ROW_NUMBER() OVER (PARTITION BY YEAR, MONTH, BRAND, CUSTOMER ORDER BY DATE DESC) AS rn FROM data ) SELECT YEAR, MONTH, BRAND, CUSTOMER, MAX(CASE WHEN rn = 1 THEN AGE END) AS LAST_AGE, COUNT(DISTINCT DATE) AS N_DAYS FROM ranked_data GROUP BY YEAR, MONTH, BRAND, CUSTOMER;
方法二:聚合函数结合窗口函数直接计算
SELECT YEAR, MONTH, BRAND, CUSTOMER, LAST_AGE, N_DAYS FROM ( SELECT YEAR, MONTH, BRAND, CUSTOMER, -- 取每个分组内DATE最大的那条记录的AGE FIRST_VALUE(AGE) OVER ( PARTITION BY YEAR, MONTH, BRAND, CUSTOMER ORDER BY DATE DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS LAST_AGE, COUNT(DISTINCT DATE) OVER (PARTITION BY YEAR, MONTH, BRAND, CUSTOMER) AS N_DAYS FROM data ) GROUP BY YEAR, MONTH, BRAND, CUSTOMER, LAST_AGE, N_DAYS;
其中方法一逻辑更清晰,执行效率也更稳定,优先推荐使用。
内容的提问来源于stack exchange,提问作者FAMG
相关产品推荐
相关产品推荐

