MIN/MAX在全NULL列上返回NULL而非报错;COALESCE需按数据类型谨慎使用;GROUP BY中全NULL组仍保留且HAVING无法过滤;业务中需明确定义NULL语义,不可仅依赖函数行为。

全NULL列上直接用MIN/MAX会返回NULL,不是报错
这是最常被误读的一点:MIN()和MAX()遇到整列都是NULL时,不会报错或中断查询,而是安静地返回NULL。比如SELECT MIN(score) FROM students WHERE class = 'X',若该班没人录入成绩,结果就是NULL——它看起来像“没查到”,但其实是函数按规则执行完毕后的合法输出。
用COALESCE兜底要分数据类型谨慎处理
COALESCE(MIN(price), 0)对数值型字段很常用,但字符串或日期字段不能随便套用:
- 字符串慎用
COALESCE(MAX(name), 'N/A'):如果真实数据里存在空字符串'',它不等于NULL,会被MAX()参与比较并可能胜出,而COALESCE只在MAX()结果为NULL时才生效,两者逻辑不重叠 - 日期字段建议先过滤再聚合:
SELECT MAX(created_at) FROM events WHERE created_at IS NOT NULL AND status = 'done',比COALESCE(MAX(created_at), '1970-01-01')更明确表达意图 - 真正需要“无数据时给默认值”的场景,优先用
COUNT()判断有效性:SELECT CASE WHEN COUNT(price) > 0 THEN MIN(price) ELSE -1 END AS min_price FROM products
GROUP BY中某组全NULL,结果仍是NULL,且无法靠HAVING筛掉
比如按地区统计订单金额极值:SELECT region, MIN(amount), MAX(amount) FROM orders GROUP BY region。若region = 'Antarctica'下所有amount都是NULL,这行仍会出现在结果中,MIN()和MAX()都为NULL。
HAVING不能用来排除这类行,因为HAVING MIN(amount) IS NOT NULL会把整组过滤掉,但你其实只想跳过“无效组”,而不是让查询变空——更稳妥的做法是在GROUP BY前用WHERE amount IS NOT NULL预过滤,或者用窗口函数+条件聚合重构逻辑。
别依赖“NULL不参与比较”就忽略业务含义
数据库层面MIN()跳过NULL是确定行为,但业务上NULL可能代表“未发生”“不可用”“需人工补录”,和“零值”“空字符串”语义完全不同。例如统计各门店日均销量,某店当天系统故障没上报数据,MIN(daily_sales)跳过NULL后返回其他店的最小值,这个结果对运营毫无意义。
关键不是函数怎么算,而是你是否在查询前已明确定义:NULL在此上下文中是否可接受?是否需要前置校验?是否应由ETL层转成0或UNKNOWN?函数本身不替你做这个判断。

















