APPROX_PERCENTILE_DISC仅SQL Server 2022+支持,仅限聚合用法(WITHIN GROUP),不支持OVER();排序列仅允许INT/BIGINT/SMALLINT/TINYINT/MONEY/SMALLMONEY/FLOAT/REAL/BIT;结果基于KLL算法非确定性,误差≤1.33%。

APPROX_PERCENTILE_DISC 只在 SQL Server 2022+ 中可用,且仅支持聚合用法(必须带 WITHIN GROUP),不支持窗口函数(不能加 OVER())。
必须用聚合上下文,不能写 OVER()
和 PERCENTILE_DISC 不同,APPROX_PERCENTILE_DISC 在 SQL Server 2022 中完全不接受 OVER() 子句。你如果强行加上,会直接报错:Incorrect syntax near 'OVER'。
它只能配合 GROUP BY 使用,或者用于无分组的全局计算:
- ✅ 正确:用
GROUP BY department计算各部门近似中位数 - ✅ 正确:不写
GROUP BY,只算全表近似 P50 - ❌ 错误:写
OVER (PARTITION BY department)—— 语法不识别 - ❌ 错误:混用普通列和
APPROX_PERCENTILE_DISC却不GROUP BY—— 报错column must appear in the GROUP BY clause
排序列类型受限,不能是 DECIMAL 或 DATE
APPROX_PERCENTILE_DISC 对 ORDER BY 列的数据类型有硬性限制:只接受明确列出的数值类型。
以下类型会被拒绝并报错 The function 'APPROX_PERCENTILE_DISC' is not supported with the specified data type:
-
DECIMAL和NUMERIC(哪怕只是DECIMAL(10,2)) -
DATE、DATETIME、TIME等时间类型 -
VARCHAR、NVARCHAR(即使内容全是数字)
只允许这些类型(来自官方文档):
-
INT、BIGINT、SMALLINT、TINYINT -
MONEY、SMALLMONEY、FLOAT、REAL -
BIT(但实际意义有限)
若原始列为 DECIMAL,需显式转成 FLOAT 或 INT(注意精度损失):APPROX_PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY CAST(sales_amount AS FLOAT))。
结果不稳定是设计使然,不是 bug
APPROX_PERCENTILE_DISC 基于 KLL 草图算法,每次执行可能返回不同值——哪怕数据、SQL 完全没变。
这不是环境或配置问题,而是预期行为。官方保证的是“基于排名的误差 ≤ 1.33%,置信度 99%”,不是结果确定性。
- 同一查询连续跑 10 次,可能得到 5 个不同结果(都在真实 P50 的 ±1.33% 排名误差内)
- 不能用于需要幂等输出的场景(如生成审计快照、对比测试基线)
- 若需稳定结果,必须降级用
PERCENTILE_DISC,哪怕慢一点
另外,NULL 值仍被自动忽略,这点和精确函数一致;但如果整列都是 NULL,函数返回 NULL,不会报错。
别和 PERCENTILE_DISC 混用在同一 SELECT 中
虽然语法上允许,但两者语义冲突:一个返回近似离散值,一个返回精确离散值,放在一起容易误导业务方以为“两个中位数应该接近”。实际上:
- 当数据量小(比如 APPROX_PERCENTILE_DISC 的误差可能反而比
PERCENTILE_DISC更大(因草图采样偏差) - 当存在大量重复值(如薪资集中在几个档位),
APPROX_PERCENTILE_DISC可能跳过高频值,选中低频边缘值 - 若报表需同时展示“精确中位数”和“近似中位数”,建议拆成两个独立查询,或加明确注释说明差异来源
最常被忽略的一点:APPROX_PERCENTILE_DISC 的性能优势只有在千万级以上数据、且服务器内存受限时才明显;小表上它未必更快,还多一层不确定性。

















