如何按多列条件GROUP BY计算分组中位数
按多列分组计算中位数的实现方法
按多列分组计算中位数的逻辑和单分组本质一致,只需把所有需要分组的字段都放到GROUP BY(或窗口函数的PARTITION BY)子句中即可。下面结合你提供的trans表,以按brand和store_country分组计算net_order_entry的中位数为例,给出不同SQL方言的实现方案:
一、MySQL(8.0+版本)
方法1:使用内置百分位函数(推荐)
MySQL 8.0+支持PERCENTILE_CONT(连续型中位数,适合数值型字段)和PERCENTILE_DISC(离散型中位数),直接结合GROUP BY多列即可:
SELECT brand, store_country, -- 连续型中位数,偶数个值时取中间两个数的平均值 PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY net_order_entry) AS median_net_entry FROM trans GROUP BY brand, store_country;
方法2:窗口函数手动计算(兼容旧版)
如果你的MySQL版本不支持百分位函数,可以用窗口函数手动排序取中间值:
WITH ranked_data AS ( SELECT brand, store_country, net_order_entry, -- 分组内按net_order_entry排序后的行号 ROW_NUMBER() OVER (PARTITION BY brand, store_country ORDER BY net_order_entry) AS rn, -- 分组内的总记录数 COUNT(*) OVER (PARTITION BY brand, store_country) AS cnt FROM trans ) SELECT brand, store_country, -- 奇数个值取中间行,偶数个值取中间两行的平均值 AVG(net_order_entry) AS median_net_entry FROM ranked_data WHERE rn IN (FLOOR((cnt + 1)/2), CEIL((cnt + 1)/2)) GROUP BY brand, store_country;
二、PostgreSQL(10+版本)
PostgreSQL 10+自带MEDIAN函数,用法非常简洁:
SELECT brand, store_country, MEDIAN(net_order_entry) AS median_net_entry FROM trans GROUP BY brand, store_country;
也可以用PERCENTILE_CONT(0.5)实现和MySQL一致的逻辑。
三、SQL Server
SQL Server支持PERCENTILE_CONT和PERCENTILE_DISC,结合GROUP BY多列使用:
SELECT brand, store_country, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY net_order_entry) OVER (PARTITION BY brand, store_country) AS median_net_entry FROM trans GROUP BY brand, store_country;
关键注意点
- 分组列可以任意组合:比如你需要按
brand、store_country、年份(YEAR(order_entry_date))三列分组,只需把这些字段都加到GROUP BY或PARTITION BY中即可 - 替换计算字段:示例中计算的是
net_order_entry的中位数,换成units_ordered、gross_order_entry等字段只需修改对应的列名 - 离散型vs连续型中位数:
PERCENTILE_DISC会返回分组中实际存在的值,PERCENTILE_CONT可能返回中间值的平均值(非原表存在的值),根据业务需求选择
内容的提问来源于stack exchange,提问作者kuliko
相关产品推荐
相关产品推荐

