PostgreSQL 13+、MySQL 5.7+ 和 MariaDB 支持 SUM(DISTINCT column),但 MySQL 存在隐式类型转换风险;SQL Server、Oracle 和 SQLite 不支持,需用子查询替代。

SUM(DISTINCT) 不是标准 SQL 函数,直接写 SUM(DISTINCT column) 在多数数据库里会报错或行为异常。
哪些数据库支持 SUM(DISTINCT column)?
PostgreSQL 从 13 版本起原生支持 SUM(DISTINCT column);MySQL 5.7+ 和 MariaDB 也支持(但有隐式类型转换风险);SQL Server 和 Oracle 完全不支持该语法,会直接报错 Incorrect syntax near 'DISTINCT' 或 ORA-30483: window functions not allowed here。
- PostgreSQL:✅ 可用,语义明确——对去重后的值求和
- MySQL:⚠️ 表面可用,但若
column是字符串或含隐式转换(如'1'和1),DISTINCT去重逻辑可能与预期不符 - SQL Server / Oracle / SQLite:❌ 语法错误,必须改写
替代方案:用子查询实现等效逻辑
在不支持 SUM(DISTINCT) 的数据库中,最稳妥写法是先 SELECT DISTINCT 再聚合:
SELECT SUM(val) FROM (SELECT DISTINCT column_name AS val FROM table_name) AS distinct_vals;
注意点:
- 子查询必须有别名(如
AS distinct_vals),否则 SQLite 和 SQL Server 会报no such column或must specify alias - 如果
column_name允许 NULL,DISTINCT会保留一个 NULL,而SUM()会忽略 NULL——结果正确,无需额外处理 - 性能上,大表 + 高基数列时,子查询可能比原生
SUM(DISTINCT)慢 2–5 倍(因需物化中间结果)
常见误用:把 DISTINCT 错放在 SUM() 外部
写成 SELECT DISTINCT SUM(column) 是典型误解——这只会去重「总和结果」,毫无意义(单个数值去重后还是它自己)。
真正想算“每个用户最后一次订单金额之和”这类场景,不能靠 DISTINCT,得用窗口函数或关联子查询:
SELECT SUM(last_order_amt) FROM ( SELECT user_id, MAX(order_time) AS max_time FROM orders GROUP BY user_id ) t JOIN orders o ON t.user_id = o.user_id AND t.max_time = o.order_time;
这里 DISTINCT 解决不了业务去重逻辑,强行套用 SUM(DISTINCT amount) 可能漏掉同一用户多笔不同金额的订单。
实际写 SQL 时,先查清自己用的数据库版本是否真支持 SUM(DISTINCT),再决定用原生语法还是子查询——别让开发环境(PostgreSQL)跑通了,上线到 SQL Server 就崩。











