COUNT()与COUNT(主键)不等→存在NULL主键,COUNT()与COUNT(DISTINCT 主键)不等→存在重复主键;推荐单条语句对比total_rows、non_null_ids、unique_ids及null_flag、dup_flag。

用 COUNT 检查空值与重复主键
主键或业务唯一键出现 NULL 或重复,是数据质量最常见硬伤。直接 COUNT(*) 无法暴露问题,得靠对比:
-
COUNT(*)和COUNT(主键字段)不等 → 存在NULL主键 -
COUNT(*)和COUNT(DISTINCT 主键字段)不等 → 存在重复主键
推荐一次性写成单条语句,避免多次扫描:
SELECT COUNT(*) AS total_rows, COUNT(id) AS non_null_ids, COUNT(DISTINCT id) AS unique_ids, CASE WHEN COUNT(*) != COUNT(id) THEN 'HAS_NULL_ID' END AS null_flag, CASE WHEN COUNT(*) != COUNT(DISTINCT id) THEN 'HAS_DUP_ID' END AS dup_flag FROM orders;
注意:若表极大,COUNT(DISTINCT) 可能触发内存溢出(尤其 Hive/Spark),此时应改用 GROUP BY + HAVING COUNT(*) > 1 分步排查。
用 SUM 校验数值型字段的合理性边界
SUM 本身不报错,但和业务逻辑对不上就是信号。比如订单表中 SUM(amount) 突然比上月跌 90%,大概率是负数冲销没过滤、或单位错成“分”没转“元”。
- 先确认是否允许负值:
SUM(CASE WHEN amount 统计负值行数 - 再看量级是否合理:
AVG(amount)和STDDEV(amount)配合看离散程度(标准差远大于均值,可能混入异常大额单) - 警惕隐式类型转换:
SUM遇到字符串字段(如'123.45')在 MySQL 中会转 0,在 PostgreSQL 中直接报错 —— 必须提前WHERE amount ~ '^[0-9.]+$'过滤
示例(检查金额字段是否全为正且无异常离群):
一款AI音频处理工具,主要用于MiniMax统一媒体生成技能,用于TokenPlan工作流。当用户要求生成音频、语音、TTS、旁白、图片、插图、姿势等媒体内容时使用,适合需要提升相关任务效率的用户。
SELECT SUM(amount) AS total_amount, AVG(amount) AS avg_amount, STDDEV(amount) AS std_amount, COUNT(*) FILTER (WHERE amount = '2024-01-01';
把 COUNT 和 SUM 组合成稽核断言脚本
真正落地时,不能只看查询结果,要让数据库自己“判断是否异常”。核心是把聚合结果转成布尔条件:
- 主键完整性断言:
HAVING COUNT(*) != COUNT(DISTINCT id) - 金额非负断言:
HAVING SUM(CASE WHEN amount 0 - 空值率阈值断言:
HAVING COUNT(*) * 0.05 (空手机号超 5% 就告警)
这类脚本常嵌入调度系统(如 Airflow 的 SqlSensor),返回空结果表示通过,返回一行则触发告警。别忘了加 WHERE 分区裁剪,否则全表扫一次就拖垮集群。
容易被忽略的 NULL 处理陷阱
COUNT(字段) 自动跳过 NULL,但 SUM(字段) 遇到全 NULL 会返回 NULL 而非 0 —— 这会导致后续计算(如除法)整体变 NULL,稽核脚本悄无声息失效。
- 永远对
SUM加COALESCE(SUM(x), 0),哪怕业务上“不可能为空” -
COUNT不能代替EXISTS:想确认“某类数据是否存在”,用SELECT 1 FROM t WHERE type='refund' LIMIT 1更快,COUNT会遍历全部 - 窗口函数里慎用:
SUM() OVER (PARTITION BY ...)若分区下全为NULL,结果也是NULL,不是 0
真实生产环境里,80% 的稽核误报都源于没处理好 NULL 的传播路径,而不是逻辑写错。










