如何在Amazon Athena中按店铺和产品计算指定时段价格中位数?
在Amazon Athena中计算店铺-产品的价格中位数
没问题,我来帮你搞定这个分组计算中位数的需求!Amazon Athena基于Presto SQL引擎,我们可以直接用Presto提供的中位数相关聚合函数来实现,下面分不同场景给出具体方案:
1. 精确计算中位数
如果你的数据集规模不大,想要得到完全精确的中位数结果,可以用以下两种函数:
1.1 连续型中位数(插值计算)
percentile_cont(0.5)会在数据量为偶数时,取中间两个价格的平均值,适合需要连续数值结果的场景:
SELECT product_id, shop_id, percentile_cont(0.5) WITHIN GROUP (ORDER BY price) AS median_price FROM data_f WHERE site_id = 10 AND year || month || day || hour >= '2020022500' AND year || month || day || hour < '2020022600' GROUP BY product_id, shop_id
1.2 离散型中位数(取实际存在的值)
percentile_disc(0.5)会直接选取排序后位于中间位置的真实价格值,适合需要结果是数据集里实际存在价格的场景:
SELECT product_id, shop_id, percentile_disc(0.5) WITHIN GROUP (ORDER BY price) AS median_price FROM data_f WHERE site_id = 10 AND year || month || day || hour >= '2020022500' AND year || month || day || hour < '2020022600' GROUP BY product_id, shop_id
2. 大数据量下的近似中位数
如果你的数据集非常庞大,精确计算中位数可能会拖慢查询速度,这时可以用approx_percentile函数做近似计算,它能在保证结果足够准确的前提下大幅提升性能:
SELECT product_id, shop_id, approx_percentile(price, 0.5) AS median_price FROM data_f WHERE site_id = 10 AND year || month || day || hour >= '2020022500' AND year || month || day || hour < '2020022600' GROUP BY product_id, shop_id
几点实用提示
- 确保
price列是数值类型(比如double、int),如果是字符串格式,记得先转换:cast(price as double)。 - 你当前的时间条件是用字符串拼接实现的,可能存在隐患(比如月份是个位数时,拼接后会变成
202012500这类不规范的字符串),建议把时间字段转换成timestamp类型后再做范围查询,示例如下:
这样既准确又能提升查询效率。WHERE site_id = 10 AND parse_datetime(concat(year, '-', month, '-', day, ' ', hour), 'yyyy-MM-dd HH') >= timestamp '2020-02-25 00:00:00' AND parse_datetime(concat(year, '-', month, '-', day, ' ', hour), 'yyyy-MM-dd HH') < timestamp '2020-02-26 00:00:00'
内容的提问来源于stack exchange,提问作者datazang




