PostgreSQL 按日期国家计算销售额占比、零值均分及去重优化
问题定位
原查询存在三个核心问题,导致输出不符合预期:
- 维度粒度不对:子查询保留了渠道级的明细行,未提前按
event_date + country维度聚合,导致同一日期同一国家只要存在多条渠道记录就会重复输出 - 外层聚合无效:最外层的
GROUP BY语句包含了渠道粒度的sales单值,无法真正合并同一国家的多行记录,因此即使尝试加DISTINCT也无法彻底去重 - 除法计算逻辑错误:原查询未做类型转换,整数相除时会被Postgres按整数规则截断,无法得到正确的小数占比
修正后的可运行查询
WITH country_daily_agg AS ( -- 第一步:按日期+国家聚合,从根源上保证每个日期每个国家仅输出1行 SELECT event_date, country, SUM(sales) AS country_sales_total FROM sales GROUP BY event_date, country ) SELECT event_date, country, -- 按规则计算占比 CASE -- 当日总销售额为0时,平均分配给当日涉及的所有国家 WHEN SUM(country_sales_total) OVER (PARTITION BY event_date) = 0 THEN ROUND( 1.0 / COUNT(country) OVER (PARTITION BY event_date), 3 ) -- 正常场景:国家销售额 / 当日全量总销售额 ELSE ROUND( country_sales_total * 1.0 / SUM(country_sales_total) OVER (PARTITION BY event_date), 3 ) END AS share_per_day_per_country FROM country_daily_agg ORDER BY event_date, country;
结果匹配说明
上述查询的输出完全对齐预期要求:
- 非0总销售额日期:按国家汇总销售额占当日总销售额的比例计算,保留3位小数
- 总销售额为0的日期:自动按当日涉及的国家数量均分占比
- 每个日期、每个国家仅输出1行,无渠道粒度导致的重复记录
内容的提问来源于stack exchange,提问作者Michi
相关产品推荐
相关产品推荐

