当前位置: 首页 > article >正文

MySQL统计指定表中各字段的空值、空字符串或零值比例

DELIMITER $$

DROP PROCEDURE IF EXISTS AnalyzeDatabase$$
CREATE PROCEDURE AnalyzeDatabase(db_name VARCHAR(64))
BEGIN
    DECLARE done BOOLEAN DEFAULT FALSE;
    DECLARE v_table_name VARCHAR(64);
    DECLARE v_column_name VARCHAR(64);
    DECLARE v_data_type VARCHAR(64);
    
    -- 游标获取所有表字段信息
    DECLARE cur CURSOR FOR 
    SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE
    FROM information_schema.COLUMNS 
    WHERE TABLE_SCHEMA = db_name;
    
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    -- 创建临时结果表
    CREATE TEMPORARY TABLE IF NOT EXISTS analysis_result (
        database_name VARCHAR(64),
        table_name VARCHAR(64),
        column_name VARCHAR(64),
        column_type VARCHAR(64),
        invalid_count INT,
        total_rows INT,
        percentage DECIMAL(20,2)
    );

    TRUNCATE TABLE analysis_result;

    OPEN cur;

    read_loop: LOOP
        FETCH cur INTO v_table_name, v_column_name, v_data_type;
        IF done THEN
            LEAVE read_loop;
        END IF;

        -- 构建动态SQL
        SET @condition = CASE 
            WHEN v_data_type IN ('char','varchar','text','tinytext','mediumtext','longtext') THEN
                CONCAT('TRIM(IFNULL(`', v_column_name, '`, "")) = ""')
            WHEN v_data_type IN ('int','tinyint','smallint','mediumint','bigint','decimal','numeric','float','double','real') THEN
                CONCAT('IFNULL(`', v_column_name, '`, 0) = 0')
            ELSE
                CONCAT('`', v_column_name, '` IS NULL')
        END;

        SET @sql = CONCAT(
            'INSERT INTO analysis_result ',
            'SELECT ',
            QUOTE(db_name), ', ',
            QUOTE(v_table_name), ', ',
            QUOTE(v_column_name), ', ',
            QUOTE(v_data_type), ', ',
            'SUM(CASE WHEN ', @condition, ' THEN 1 ELSE 0 END), ',
            'COUNT(*), ',
            'ROUND((SUM(CASE WHEN ', @condition, ' THEN 1 ELSE 0 END) * 100.0 / NULLIF(COUNT(*), 0)), 2) ',
            'FROM ', db_name, '.', v_table_name
        );

        -- 执行动态SQL
        PREPARE stmt FROM @sql;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    END LOOP;

    CLOSE cur;

    -- 输出最终结果
    SELECT * FROM analysis_result;
    
    -- 清理临时表(可选)
    DROP TEMPORARY TABLE IF EXISTS analysis_result;
END$$

DELIMITER ;

-- 使用示例:分析mydatabase数据库
CALL AnalyzeDatabase('your_database_name');

使用说明:

  1. 将代码中的’your_database_name’替换为需要分析的数据库名称
  2. 执行后会返回包含以下列的结果集:
    • database_name:数据库名称
    • table_name:表名称
    • column_name:字段名称
    • column_type:字段类型
    • invalid_count:异常值数量(空字符串/0/NULL)
    • total_rows:表总行数
    • percentage:异常值占比

实现特点:

  1. 自动识别字段类型并应用不同的处理逻辑
  2. 使用临时表存储中间结果
  3. 处理了除零错误(使用NULLIF)
  4. 百分比计算保留两位小数
  5. 自动遍历指定数据库的所有表和字段

注意事项:

  1. 需要具有访问information_schema的权限
  2. 对大型数据库可能需要较长时间执行
  3. 结果中的total_rows是每次查询时的实时行数
  4. 精确度取决于表数据量和服务器性能

http://www.kler.cn/a/545272.html

相关文章:

  • 面试经典150题——堆
  • 科技之光闪耀江城:2025武汉国际半导体产业与电子技术博览会5月15日盛大开幕
  • Django开发入门 – 3.用Django创建一个Web项目
  • git: 如何查询某个文件或者某个目录的更新历史
  • 前端开发工程中如何利用DeepSeek提升工作效率:实战案例与策略解析
  • go语言获取机器的进程和进程运行参数 获取当前进程的jmx端口 go调用/jstat获取当前Java进程gc情况
  • Redis 集群:从基础到实战的面试指南
  • 20250213编译飞凌的OK3588-C_Linux5.10.209+Qt5.15.10_用户资料_R1
  • 从 Windows Forms 到微服务的经验教训
  • Ubuntu20.04上搭建nginx正向代理提供上网服务
  • rdian是一个结构体,pdian=^Rdian,list泛型做什么用?
  • Android 消息总站 设计思路
  • 修改RAGFlow在docker desktop中的容器名
  • 《刚刚问世》系列初窥篇-Java+Playwright自动化测试-22- 操作鼠标拖拽 - 下篇(详细教程)
  • QT:Button
  • 布隆过滤器(简单介绍)
  • Pro Git --(Windows)总结
  • DeepSeek整理PDF文档以思维导图方式展示
  • TOML介绍
  • Spring Boot(8)深入理解 @Autowired 注解:使用场景与实战示例