使用PERCENTILE_DISC分区聚合求中位数出现重复行如何解决?
问题原因
PERCENTILE_DISC 作为窗口函数运行时,会为分区内的每一行都返回相同的中位数结果,所以每个日期有多少条原始记录,就会返回多少条重复的中位数行。
不用GROUP BY的解决方案
- 方法1:直接加
DISTINCT去重
这是最简单的方案,同一个日期对应的中位数结果完全一致,直接对查询结果去重即可,不需要修改核心计算逻辑,适配所有支持窗口函数的SQL引擎。
代码示例:SELECT DISTINCT Bike.date date, PERCENTILE_DISC( IFNULL(Bike.NetB2CRevenue, 0), 0.5 ) OVER(PARTITION BY Bike.date ) AS MedianRevenuePer FROM #Table as Bike - 方法2:用
ROW_NUMBER()窗口函数取每个分组的首行
如果你后续还要在同一个查询逻辑里保留更多和日期绑定的其他字段,或者部分SQL引擎对窗口函数的DISTINCT支持不好,可以给每个日期的行编号,筛选序号为1的行即可实现去重。
代码示例:WITH temp AS ( SELECT Bike.date date, PERCENTILE_DISC( IFNULL(Bike.NetB2CRevenue, 0), 0.5 ) OVER(PARTITION BY Bike.date ) AS MedianRevenuePer, ROW_NUMBER() OVER(PARTITION BY Bike.date ORDER BY Bike.ID) AS rn FROM #Table as Bike ) SELECT date, MedianRevenuePer FROM temp WHERE rn = 1 - 方法3:使用子查询预先计算中位数再关联
如果你的大查询需要把中位数结果和原表的其他明细字段结合使用,不想直接对整个结果去重,可以先单独计算每个日期的中位数,再通过日期关联回原表的明细逻辑,完全不影响原有复杂查询的其他逻辑。
代码示例:WITH date_median AS ( SELECT date, PERCENTILE_DISC( IFNULL(NetB2CRevenue, 0), 0.5 ) OVER(PARTITION BY date ) AS MedianRevenuePer FROM #Table GROUP BY date, NetB2CRevenue ) SELECT b.*, dm.MedianRevenuePer FROM #Table b LEFT JOIN date_median dm ON b.date = dm.date
内容的提问来源于stack exchange,提问作者Aleko
相关产品推荐
相关产品推荐

