大家好!在校园或企业的日常管理中,你是否经历过被海量、混乱的 Excel 考勤打卡数据支配的恐惧?每次统计迟到、早退,不仅耗时耗力,还总是因为口径不一、数据缺失导致结果频频出错。

都说“数据分析项目中,80% 的时间都在做数据清洗”,这句话我这次是彻底领悟了!今天,我将带大家完整走一遍商业数据分析中最硬核、也最实用的环节——ETL(数据的提取、转换与加载)

本文绝不是那种只讲理论的“空中楼阁”,而是一份基于真实业务数据集(“数智教育”大赛数据集)、使用可视化零代码平台(助睿数智 Uniplore)打造的纯干货实战笔记。从零基础建库导表,到手写 JS 脚本做标签衍生,再到最后的数据多表关联与落库,每一步的操作我都做了一比一的截图拆解。

⚠️ 高能预警(干货必看): 教程的第四部分,我独家复盘了在真实数据加工中踩过的 7 大致命“天坑”(包括极为隐蔽的数据库主键冲突、映射错位、脏数据引发的连环报错等)以及我的终极排雷方案!

强烈建议大家点赞、收藏,跟着这篇保姆级教程,一起开启我们的数据清洗打怪升级之路吧!🚀

第一部分:实验背景

1. 实验目的

在现代校园管理中,考勤统计往往面临着人工统计效率低、口径不统一等痛点。本次实验旨在基于真实的“数智教育”大赛数据集,设计并实现一个“学生多维度考勤统计”的 ETL(提取、转换、加载)数据转换流。

通过这次实验,我希望能够掌握 ETL 数据处理的全流程(数据接入、关联、衍生、聚合、落地),并且结合实际数据的脏数据情况,优化空值处理与标签提取逻辑,最终输出精准的考勤多维度统计结果,为校园考勤管理提供有效的数据支撑。

2. 实验环境

  • 使用平台:助睿数智(Uniplore)一站式数据科学实验平台

  • 实验平台地址https://lab.guilian.cn/

  • 数据源:“数智教育”大赛数据集(本次聚焦核心的 3 张表:考勤主表 3_kaoqin.csv、考勤类型码表 4_kaoqintype.csv、学生信息表 2_student_info.csv

  • 实验设备:个人计算机(通过浏览器访问助睿零代码在线平台,具备 MySQL 数据库连接权限)

3. 处理流程简述

本转换流替代了传统的人工 Excel 统计,实现了从原始打卡数据到标准化结果的自动化闭环处理。核心逻辑为:接入三大数据源 → 多表关联 → 标记考勤行为 → 计算核心指标 → 基础属性关联 → 落地统计结果

为了直观展示整个流转过程,我绘制了如下的 ETL 逻辑架构图:

第二部分:实验步骤

这是整个实验最核心的部分,我们将全流程拆解为从零开始的操作记录。

步骤一:创建实验项目与数据资源准备

操作说明: 首先在助睿平台创建一个专属的实验项目,并将公共空间的数据集导出到我们的私有目录中,方便后续处理。

配置要点:

  1. 登录系统后,点击“新建项目”

  2. 输入项目名称“学生用户画像标签构建”,点击“确定”。

  3. 进入项目

  4. 点击左侧菜单“文件库”,右键根目录点击“新建目录”,输入目录名称“数智教育数据集”。

  5. 进入“公共空间” -> “数据资源”

  6. 找到实验所需的三张表(3_kaoqin.csv4_kaoqintype.csv2_student_info.csv),依次点击卡片右上角的“更多”->“导出”

  7. 选择导出到刚刚新建的私有目录下

  8. 刷新看到导出成功

步骤二:建立数据源连接

操作说明: ETL 处理需要一个可以执行 SQL 的关系型数据库环境。我们在平台的“元数据”管理中建立“团队私有数据库”的连接。

配置要点:

  1. 在左侧菜单点击“元数据”标签页,在“关系数据库”节点上右键选择“新建数据源”。

  2. 连接类型选择“MySQL”,填写助教提供的服务器主机名、端口号(3306)、数据库名称以及账号密码。

  3. 填写完毕后点击“添加”。可以看到添加成功

步骤三:原始数据建表与CSV数据入库

操作说明: 我们需要分别创建 3 张原始表和 1 张目标标签表,并将刚才导出的 CSV 数据分别灌入对应的原始数据库表中。

配置要点:

  1. 导入原始考勤记录表 (3_kaoqin.csv)

    • 建表:新建转换流命名为“创建原始_学生考勤表”拖入“执行一个SQL脚本”组件在组件中填写SQL脚本

      CREATE TABLE IF NOT EXISTS  `raw_attendance` (
        `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
        `attendance_id` varchar(64) DEFAULT NULL COMMENT '考勤ID',
        `learn_term` varchar(30) DEFAULT NULL COMMENT '学期',
        `data_datetime` varchar(50) DEFAULT NULL COMMENT '时间和日期',
        `attendance_type_id` varchar(64) DEFAULT NULL COMMENT '考勤类型ID',
        `attendance_name` varchar(100) DEFAULT NULL COMMENT '考勤名称',
        `attendance_task_order_id` varchar(64) DEFAULT NULL COMMENT '考勤事件ID',
        `stu_id` varchar(64) DEFAULT NULL COMMENT '学生ID',
        `stu_name` varchar(100) DEFAULT NULL COMMENT '学生姓名',
        `cla_name` varchar(100) DEFAULT NULL COMMENT '班级名',
        `cla_id` varchar(64) DEFAULT NULL COMMENT '班级ID',
        `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间',
        PRIMARY KEY (`id`),
        KEY `idx_student_id` (`stu_id`),
        KEY `idx_term` (`learn_term`)
      ) COMMENT='原始_学生考勤表';

      选择目标数据库连接“团队私有数据库”,确保脚本执行权限;完成后运行转换流,运行过程会定时刷新组件状态,并画布下面显示执行日志。

    • 导数:新建转换流命名为“导入原始考勤数据”拖入“CSV文件输入”组件双击CSV文件输入组件,在步骤名称中输入“考勤记录”,读取 3_kaoqin.csv编码选 UTF-8,点击“获取字段”接下来拖拽一个“表输出”组件到画布并创建“考勤记录”CSV文件输入组件到“表输出”组件的连线,连线类型选择“主输出步骤”

      双击“表输出”组件,基本配置中,数据库连接选择“团队私有数据库”,目标表输入我们使用SQL组件创建的“raw_attendance”,具体配置如下:

      点击“数据库字段”,在空白处右键“获取字段”将表字段修改为建表语句中对应的字段,点击“确认”完成后运行转换流,运行过程会定时刷新组件状态,并画布下面显示执行日志。

  2. 导入原始考勤类型表 (4_kaoqintype.csv)

    • 建表:新建转换流命名为“创建原始_考勤类型表”拖入“执行一个SQL脚本”组件执行建表 SQL创建 raw_attendance_type 表。

      DROP TABLE IF EXISTS `raw_attendance_type`;
      
      CREATE TABLE IF NOT EXISTS `raw_attendance_type` (
        `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
        `attendance_type_id` varchar(64) NOT NULL COMMENT '考勤类型id',
        `attendance_type_name` varchar(100) DEFAULT NULL COMMENT '考勤类型名称',
        `attendance_task_order_id` varchar(64) DEFAULT NULL COMMENT '考勤事件id',
        `attendance_task_name` varchar(100) DEFAULT NULL COMMENT '考勤事件名',
        `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间',
        PRIMARY KEY (`id`)
      )COMMENT='原始_考勤类型表';

      运行转换流

    • 导数:新建转换流命名为“导入原始考勤类型数据”拖入“CSV文件输入”组件。双击进行编辑。特别注意:此文件的列分隔符需改为“插入制表符(TAB)”,编码必须选择“GB2312”,否则会乱码! 随后导入“表输出”组件,表输出组件的配置同之前一样

      连线配置完成后执行转换流,运行过程会定时刷新组件状态,并画布下面显示执行日志
  3. 导入原始学生基本信息表 (2_student_info.csv)

    • 建表:新建转换流“创建原始_学生信息表”执行建表 SQL,创建 raw_student_info

      CREATE TABLE IF NOT EXISTS `raw_student_info` (
        `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
        `stu_id` varchar(64) NOT NULL COMMENT '学生ID',
        `stu_name` varchar(100) DEFAULT NULL COMMENT '学生姓名',
        `stu_sex` varchar(10) DEFAULT NULL COMMENT '性别',
        `stu_nation` varchar(50) DEFAULT NULL COMMENT '民族',
        `born_date` varchar(10) DEFAULT NULL COMMENT '出生日期(年)',
        `cla_name` varchar(100) DEFAULT NULL COMMENT '班级名',
        `native_place` varchar(200) DEFAULT NULL COMMENT '家庭住址',
        `residence_type` varchar(50) DEFAULT NULL COMMENT '家庭类型',
        `policy` varchar(50) DEFAULT NULL COMMENT '政治面貌',
        `cla_id` varchar(64) DEFAULT NULL COMMENT '班级ID',
        `cla_term` varchar(30) DEFAULT NULL COMMENT '班级学期',
        `live_on_campus` varchar(10) DEFAULT NULL COMMENT '是否住校',
        `leave_school` varchar(10) DEFAULT NULL COMMENT '是否退学',
        `dormitory_no` varchar(50) DEFAULT NULL COMMENT '宿舍号',
        `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '入库时间',
        PRIMARY KEY (`id`),
        UNIQUE KEY `uk_student_id` (`stu_id`),
        KEY `idx_cla_id` (`cla_id`)
      ) COMMENT='原始_学生信息表';

      运行转换流

    • 导数:创建“导入原始学生基本信息数据”转换流读取 CSV 文件bf_leaveSchool 字段类型修改为 String特别注意:为了避免 bf_zhusubf_qinshihao 出现浮点小数(如1.0),需要在 CSV 和 表输出 之间加入一个“字段选择”组件,在“元数据”标签页将其类型强制指定为 Integer

      拖拽“字段选择”组件到画布中,创建“CSV文件输入”组件到“字段选择”组件的连线,连接线类型选择“主输出步骤”双击“字段选择”组件,在配置窗口中,点击“元数据”,并在空白处插入2行,将“bf_zhusu”、“bf_qinshihao”字段的元数据设置如下:使用“表输出”组件将“2_student_info.csv”数据输出到团队私有数据库的“raw_student_info”中执行转换流:
  4. 创建目标结果表

    新建转换工作流,并命名为“创建学生考勤主题标签表”在该工作流中拖拽“执行一个SQL脚本”组件,通过执行SQL脚本来创建一个标签表。
    CREATE TABLE IF NOT EXISTS student_attendance_stats (
        id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增主键',
        student_id INT NOT NULL COMMENT '学生ID', 
        student_name VARCHAR(50) NOT NULL COMMENT '学生姓名',
        class_id INT NOT NULL COMMENT '班级ID',
        class_name VARCHAR(50) NOT NULL COMMENT '班级名称',
        grade VARCHAR(10) NOT NULL COMMENT '年级',
        gender VARCHAR(10) NOT NULL COMMENT '性别',
        birth_date  VARCHAR(10) NOT NULL COMMENT '出生日期',
        political_status VARCHAR(20) NOT NULL COMMENT '政治面貌',
        is_boarder VARCHAR(10) NOT NULL COMMENT '是否住校',
        campus_type VARCHAR(10) NOT NULL COMMENT '校区类型',
        late_count INT NOT NULL DEFAULT 0 COMMENT '迟到次数',
        early_leave_count INT NOT NULL DEFAULT 0 COMMENT '早退次数',
        leave_count INT NOT NULL DEFAULT 0 COMMENT '请假次数',
        uniform_violate_count INT NOT NULL DEFAULT 0 COMMENT '没穿校服次数',
        create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '统计入库时间',
        INDEX idx_student (student_id),
        INDEX idx_class (class_id),
        INDEX idx_grade (grade)
    )  ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生考勤主题标签表';
    执行转换流:

步骤四:构建核心 ETL 转换流(学生考勤主题标签构建)

现在进入数据加工环节。

数据转换流逻辑说明

转换流遵循“数据接入—清洗整合—维度拆解—标签标记—指标计算—结果落地”的核心逻辑:

  • 数据接入:接入考勤原始打卡表、考勤类型码表、学生信息基础表

  • 数据整合:多表关联,给原始打卡记录绑定学生班级、住校属性、考勤事件名称

  • 标签标记:通过考勤事件名称自动识别迟到、早退、请假、未穿校服等行为

  • 指标计算:按日核算在校时长,按多维度聚合统计各类异常次数

  • 结果落地:统一写入考勤统计结果表,供报表、查询、分析直接使用

各组件作用:

组件 作用
表输入 读取数据库中的原始数据表
排序记录 按照指定字段对数据进行排序,为记录集连接做准备
记录集连接 按关联字段连接两表,补充考勤行为名称或学生属性
字段选择 移除冗余字段,保留核心必要字段
JavaScript脚本 执行脚本,通过关键词匹配提取异常考勤记录,生成二进制标记
分组 按指定维度分组,使用SUM函数聚合统计各类异常次数
替换NULL值 将空值字段替换为“未知”
值映射 将住校状态编码(0/1)映射为“否”/“是”
表输出 输出最终结果到数据库目标表

新建转换流并命名为“学生考勤主题标签”解锁画布后,按以下步骤搭建完整流向​​​。

4.1 数据接入

操作说明:拖拽 3 个“表输入”组件至画布。

配置要点:双击第一个表输入组件,在配置窗口中,步骤名称修改为“考勤记录”,数据库连接选择“团队私有数据库”,并点击“获取SQL查询语句”在数据库中选择“raw_attendance”原始_学生考勤表系统提示弹窗中点击“确认”

同样的,参考以上步骤,将“表输入 1”和“表输入 2”组件分别命名为“考勤类型”和“学生信息”,分别获取“raw_attendance_type”考原始_考勤类型表和“raw_student_info”原始_学生信息表所有字段数据

4.2 关联考勤记录与考勤类型

操作说明:将考勤记录和考勤类型拼接,获取具体的考勤行为名称。

使用表输入组件读取考勤记录、考勤类型数据后,需通过记录集连接组件完成数据关联,补充关键业务信息,为后续指标计算奠定基础。

使用记录集连接组件,将考勤主表与考勤类型码表关联——因为考勤记录表只有考勤类型ID(attendance_type_id)和考勤任务顺序ID(control_task_order_id ),缺少具体的考勤行为名称,而通过记录集连接组件进行连接,即可为每条考勤记录补充“正常考勤”“没穿校服”“迟到”“请假”等具体行为信息,确保后续能准确识别各类考勤行为。具体操作如下:

配置要点

  • 在组件库搜索“记录集连接”组件,并将组件拖拽至画布中
  • 创建“考勤记录”CSV文件输入组件到记录集连接组件的连接线。出现“排序需要”的提示。这是由于记录集连接组件是按接收数据的顺序进行记录关联的,如果接收的数据是无序的,可能会造成记录连接结果出错。
  • 为避免因为排序问题造成连接结果出错。添加一个排序记录组件到转换流的“考勤记录”与“记录集连接”之间。
  • 双击“排序记录”组件,通过“获取字段”功能获取字段列表,然后删除多余字段,只保留“attendance_type_id”、“attendance_task_order_id”字段。

  • 创建“考勤类型”表输入组件到记录集连接组件的连接线。由于“考勤类型”组件的记录默认是按“attendance_type_id”、“attendance_task_order_id”这两个字段升序记录的,所以无需再次排序
  • 双击记录集连接组件,在下拉列表中选择需要连接的数据来源,第一个Transform选择“按照考勤类型和考勤任务类型排序”,第二个Transform选择“考勤类型”,连接类型选择LEFT OUTER
  • 点击Transform的连接字段中的“获得连接字段”按钮,即可获取字段
  • 2个Transform字段中仅保留“attendance_type_id”、“attendance_task_order_id”字段,这样做表示使用这2个字段进行记录连接
4.3 行为标签衍生(提取异常考勤记录)

操作说明:根据关联出的考勤名称,打上 0 或 1 的二进制标签。

配置要点:添加“JavaScript 代码”组件

双击“JavaScript代码”组件,命名为“提取异常考勤记录”,在Script1中输入JavaScript脚本

// 核心判断逻辑
if(attendance_type_name != null && attendance_task_name != null){

    // 迟到判断(排除请假)
    if((attendance_type_name.includes("迟到") || 
        attendance_type_name.includes("晚到") || 
        attendance_task_name.includes("迟到") || 
        attendance_task_name.includes("晚到")) && 
        !attendance_task_name.includes("请假")){
      isLate = 1;
    }

    // 早退判断(排除请假)
    if((attendance_type_name.includes("早退") || 
        attendance_task_name.includes("早退")) && 
        !attendance_task_name.includes("请假")){
      isEarly = 1;
    }

    // 校服违规:只要包含“校服”就标记违规
    if(attendance_type_name.includes("校服") || attendance_task_name.includes("校服")){
      isNoUniform = 1;
    }
}

// 请假判断
if(attendance_task_name != null){
    if(attendance_task_name.includes("请假")){
      isLeave = 1;
    }
}

使用“获取变量”获取输出字段,系统将自动解析脚本中变量定义代码,生成字段数据点击“测试脚本”按钮,确认标记字段(is_late_early、is_leave等)仅存在1和0两个值,标签判断准确(如迟到记录对应is_late_early=1,正常出勤对应is_compliant=1),无异常

4.4 多维度分组聚合统计

操作说明:将明细数据按学生和班级聚合。

配置要点:添加“分组”组件,并建立连接线,连线选择“主输出步骤”分组字段选择 stu_id, stu_name, cla_id, cla_name聚合字段通过 SUM 函数分别对上一步提取的 isLate, isEarly, isLeave, isNoUniform 等标记进行求和,生成具体的次数指标。

4.5 关联学生基础属性

操作说明:将聚合后的统计数据与学生信息表拼接。

配置要点

  • 必须排序:在“分组输出”后接一个“排序记录”,命名成“考勤数据按学号排序”,按 stu_id 排序在“学生信息表”输入后也接一个“排序记录”,命名成“按照学生编号进行排序”,按 stu_id 排序。

  • 添加第二个“记录集连接”组件,配置 LEFT OUTER 关联,连接字段为 stu_id

    创建“考勤数据按学号排序”记录排序组件到记录集连接 1组件的连线,关联学生信息和考勤记录信息记录集连接 1组件的第一个Transform选择“考勤数据按学号排序”,第二个Transform选择“按照学生编号进行排序”,连接类型选择LEFT OUTER点击“获得连接字段”按钮,第一个Transform字段保留“stu_id”,第二个Transform字段保留“stu_id”
4.6 字段选择(移除冗余)

操作说明:清洗拼接后的“大宽表”,去除无效字段。

配置要点:添加“字段选择”组件,创建“记录集连接 1”组件到字段选择组件的连接线在“移除”标签页中,删除以下字段,其他字段全部保留

  • 学生 ID(stu_id)
  • 学生姓名(stu_name)
  • 班级 ID(cla_id)
  • 班级名称(cla_name)
  • 迟到次数(late_count);
  • 早退次数(early_count);
  • 请假次数(leave_count);
  • 没穿校服次数(no_uniform_count)
  • 性别(stu_sex)
  • 出生日期(born_date)
  • 政治面貌(policy)
  • 是否住校(live_on_campus)

在字段选择组件鼠标右键弹出菜单,点击“显示输出字段”,查看输出字段是否正确

4.7 空值处理

操作说明:处理基础属性中的缺失值。

配置要点:添加“替换NULL值”组件,创建“移除冗余字段”字段选择组件到“替换NULL值”组件的连线,连线类型选择“主输出步骤”勾选“选择字段”,将 stu_sex, born_date, policy, live_on_campus 这四个字段的空值统一替换为字符串文本“未知”。

4.8 基础属性标准化(住校映射、提取年级/校区)

操作说明:规范数据格式,衍生新的画像维度。

配置要点

  1. 值映射:添加“值映射”组件,并创建替换NULL值组件到值映射组件的连线,并选择“主输出步骤”步骤名称改为“住校状态映射”,字段选 live_on_campus,不匹配时的默认值为“否”。在下方字段值表格空白处右键,点击“插入”,将源值 0 目标值映射为 ,源值 1 映射为

    1. 提取年级:添加“JavaScript代码”组件,创建住校状态映射组件到JavaScript代码组件的连线编写代码根据 cla_name 是否包含“高一/高二/高三”生成 gra_name 字段。

      var gra_name
      if (cla_name == null){
        gra_name='未知'
      }else if(cla_name.includes('高一')){
        gra_name='高一'
      }else if (cla_name.includes('高二')){
        gra_name='高二'
      }else if (cla_name.includes("高三")){
        gra_name='高三'
      } else{
        gra_name='未知'
      }

      步骤名称改为“从班级提取年级”,并输入代码:接下需要设置“gra_name”字段类型,在配置窗口的下方空白表格处右键,点击“插入”,字段名称输入“gra_name”,类型为“String”,替换“字段名”或“重命名”值选择“否”,设置完成后点击“确认”

  2. 判定校区:继续添加“JavaScript代码”组件,命名为“校区类型判定”,输入的代码如下:

    var class_campus_type
    if (cla_name == null){
      class_campus_type='未知'
    }else if(cla_name.startsWith('白-') || cla_name.startsWith('东-')){
      class_campus_type='新校区'
    }else if (cla_name != null && !isEmpty(cla_name)){
      class_campus_type='老校区'
    } else{
      class_campus_type='未知'
    }

    字段名称“class_campus_type”,类型为“String”,替换“字段名”或“重命名”值选择“否”

4.9 结果入库与执行流转

操作说明:将最终干净、标准的数据写入目标数据库表中。

配置要点

  1. 在流末尾接上“表输出”组件,创建“校区类型判定”“JavaScript代码组件到表输出组件的连线数据库连“团队私有数据库”,目标表选 student_attendance_stats务必勾选“裁剪表”(避免重复执行时数据叠加)以及“指定数据库字段”。

  2. 在“数据库字段”标签页,点击获取字段,核对并调整映射关系,确保流转字段写入对应的表列中。

  3. 保存转换流,点击顶部工具栏的“执行”按钮。

第三部分:实验结果

转换流执行完毕后,点击“元数据”tab页,在“团队私有数据库”连接上右键选择“加载元数据”然后进入数据探查页面,展开“团队私有数据库”,双击目标表 student_attendance_stats 查看最终的数据结果。

结果分析与验证: 数据成功产出并展现了多维度的学生画像:

  1. 基础属性完整:包含学生唯一的 ID、班级、性别、年龄、政治面貌。

  2. 衍生维度清晰:通过提取,我们清晰看到了学生的“年级”与“校区类型”(新/老校区),以及标准化为中文“是/否”的住校状态。

  3. 行为统计精准:原先海量的单条打卡流水,被成功聚合成了每位学生的 late_count(迟到次数)、early_leave_count(早退次数)、leave_count(请假次数)和没穿校服次数。

通过抽查几个特定的学号与原始数据比对,发现迟到次数成功排除了正常请假的记录,空值也全部被优雅地替换成了“未知”。这份数据现在已经可以直接接入 BI 看板进行可视化展示了。

第四部分:问题与解决

在整个配置过程中,并不是一帆风顺的,这里记录几个我踩过的坑和排雷过程:

问题 1:记录集连接后出现数据严重错乱 / 漏数据

  • 问题现象:在将“考勤记录表”和“考勤类型表”使用 记录集连接 组件拼接后,发现输出结果丢失了大量数据,有些匹配结果完全是乱码或张冠李戴。

  • 问题原因:这是因为助睿(乃至类似 Kettle 等 ETL 工具)的“记录集连接”是基于流的排序合并算法(Merge Join),它要求输入的两个数据流必须提前按照连接键进行排序。

  • 解决方法:在进行连接之前,在两个输入流的连线上都强制加上一个“排序记录”组件,并指定依据 attendance_type_idattendance_task_order_id 进行升序排列。排完序后再做 Join,数据瞬间完美匹配。

问题 2:住校状态与宿舍号出现奇怪的小数点(如 1.0)

  • 问题现象:在导入原始的 2_student_info.csv 时,本来只有 1 和 0 的住校状态变成了浮点数,影响了后面的文本匹配和值映射。

  • 问题原因:CSV文件输入组件在自动“获取字段”时,将数字全部推断为了 Number(双精度浮点)类型。

  • 解决方法:在读取 CSV 之后加了一个“字段选择”组件,在“元数据”配置页中,强行将 bf_zhusubf_qinshihao 的类型指定为 Integer,从源头掐断了小数点的产生。

问题 3:导入考勤类型表全量乱码

  • 问题现象:使用表输入读取 4_kaoqintype.csv 时全是乱码,字段全部粘连在一起。

  • 问题原因:该源文件的编码格式和分隔符与常规的 UTF-8 和逗号分隔不同。

  • 解决方法:打开 CSV 输入配置,将分隔符改为“插入制表符(TAB)”,将文件编码修改为 GB2312,重新获取字段即可恢复正常。

问题 4:重复执行转换流导致唯一键冲突报错 (Duplicate entry)

  • 问题现象:在将考勤类型表 CSV 导入数据库执行转换流时,日志出现一片标红报错:java.sql.BatchUpdateException: Duplicate entry '1003' for key 'raw_attendance_type.uk_attendance_type_id',导致任务直接失败。

  • 问题原因:这是因为在建表阶段,我们为了保证数据严谨性,为该表的考勤事件 ID 加上了 UNIQUE KEY(唯一键)约束。之前我在排查乱码时曾经执行过一次该转换流且有数据成功入库,当我再次点击“执行”时,组件试图将相同的数据进行追加插入(Append),新旧数据主键冲突,从而触发了该拦截报错。

  • 解决方法:这是典型的破坏 ETL “幂等性”的操作。为了保证重跑安全,需要双击打开“表输出”组件,在基本配置页面中勾选“裁剪表”(Truncate table)选项。这样在每次执行插入动作前,组件都会自动清空表里的历史脏数据,完美避免主键冲突问题。

问题 5:神坑!勾选了“裁剪表”依然报唯一键冲突报错!(洞察数据字典真相)

  • 问题现象:接上一个问题,当我老老实实勾选了“裁剪表”之后,本以为能顺利执行,结果系统依然报错 Duplicate entry '1003' for key 'raw_attendance_type.uk_attendance_type_id'!既然每次插入前表都被清空了,为什么还会报重复呢?

  • 问题原因与深度洞察:带着疑惑我直接查阅了 4_kaoqintype.csv 的原始数据文件,发现了真相!在这份考勤类型字典里,同一考勤大类下天然包含了多个子任务(例如 controler_id=1001 包含了“早上迟到”、“晚到学校”等 4 条记录;1003 也包含 3 条不同记录)。这意味着 1001、1002、1003 在源数据中全都是重复的! 官方实验文档提供的建表语句中,给字段强行加了唯一约束 UNIQUE KEY uk_attendance_type_id (...),这完全违背了业务数据“一对多”的客观规律。至于日志为什么只报了 1003 冲突? 这是因为 ETL 插入时采用的是批量提交(Batch Insert,一次提交 1000 条),当 MySQL 在处理这批数据发现 1001、1002、1003 纷纷报错时,抛出的 BatchUpdateException 通常只会捕获并在日志中打印这批错误中某一个索引的值(恰巧是 1003)。其实整批数据都因违反了错误设定的唯一约束而全盘崩溃了!

  • 解决方法:破除这个文档陷阱!我们回到“创建原始_考勤类型表”的脚本转换流中,修改建表 SQL。在最前面加上 DROP TABLE IF EXISTS raw_attendance_type;,并删掉 SQL 最后那句不合理的 UNIQUE KEY ... 约束。重新跑一次建表流,然后再运行刚才一直报错的数据导入流,数据瞬间丝滑入库!

问题 6:最后入库时报错“Unknown column 'stu_sex' in 'field list'”

  • 问题现象:执行“学生考勤主题标签”完整转换流时,前面关联和聚合步骤都成功了,但在最后的“表输出”组件报错失败,日志提示 Unknown column 'stu_sex' in 'field list'

  • 问题原因:这是因为源数据字段名与数据仓库目标表的规范字段名不一致导致的映射错位。建立目标表 student_attendance_stats 时,我们设定的字段名是规范的英文,例如 gender(性别)、student_id(学号)、birth_date(出生日期)。而 ETL 整个流向中,数据依旧沿用着原始表的字段名 stu_sexstu_idborn_date。在表输出组件中,如果没有手动指定映射,系统试图按原名硬插入,导致在数据库找不到对应的列。

  • 解决方法:双击打开最后一个“表输出”组件。

    1. 在“基本配置”标签页中,确保勾选了 “指定数据库字段”

    2. 切换到顶部的 “数据库字段” 标签页。

    3. 点击“获取字段”并在表格中手动调整对应关系:将左侧表字段 gender 映射给右侧流字段 stu_sexstudent_id 对应 stu_idbirth_date 对应 born_date 等等。

    4. 确保所有业务字段精准匹配后点击确定,再次执行即可解决映射错位。

问题 7:最后入库时连环报错“Column cannot be null” (脏数据非空拦截与类型陷阱)

  • 问题现象:解决了字段映射后满心欢喜再次执行,结果依然在最后的“表输出”频繁报错,先是报 Column 'class_name' cannot be null,处理完之后又接着报 Column 'class_id' cannot be null,导致任务崩溃。

  • 问题原因:这是真实的脏数据与严格的数据库规范产生的碰撞。在目标数据库建表时,出于对数据质量的要求,规定了班级名称(class_name)、班级ID(class_id)等核心字段为 NOT NULL(非空约束)。但是在真实的打卡数据流水(3_kaoqin.csv)中,数据是“脏”的,存在部分打卡记录压根没有带出班级信息(为空值 Null)。当流转组件试图把这些带有 Null 值的记录写入非空列时,直接被数据库无情拦截。

  • 解决方法:这正是 ETL 过程清洗阶段要干的活。回到画布中,找到之前配置好的 “替换NULL值” 组件:

    1. 插入一行,将流字段 cla_name(字符串类型)加进去,统一将其空值替换为文本 未知。顺手把 stu_name 也按此处理。

    2. 数字类型替换极易踩坑的细节: 再次插入一行处理 cla_id,但千万不能替换为“未知”!因为目标表中 class_id 是整数类型(INT),如果塞入中文会导致类型转换报错。因此,这里必须把替换值设置为数字 -1(或 0),以此作为未知 ID 的标识。 保存后重跑转换流,不同数据类型的空值均被合理填补,数据终于 100% 顺利入库!

第五部分:实验总结

我的收获

通过本次综合实验,我真真切切地走通了数据分析中至关重要的 ETL(提取-转换-加载)流

  1. 数据建模思维:深刻体会了“事实表 + 维度表 + 属性表”的星型模型魅力。

  2. 业务逻辑的抽象:学会了如何利用 JavaScript 将模糊的业务规则(如“迟到但排除请假算真迟到”、“包含‘白’字算新校区”)转化为确定的二进制标签。

  3. 数据洁癖养成:深刻认识到空值处理(替换为未知)、冗余字段清理以及类型规范的必要性,脏数据直接影响聚合统计的死活,同时掌握了 ETL 重跑防冲突(裁剪表)的幂等性设计,更重要的是,学会了对文档提供的脚本进行批判性思考,结合原始数据探查真相,绝不盲从。

对平台的整体评价

本次使用的 助睿数智(Uniplore) 平台表现相当惊艳! 作为一个零代码在线工具,它完全免去了我们在本地搭建 Hadoop/Spark 环境或者写大量繁琐 Python 脚本的痛苦。拖拽式的可视化画布(尤其是像画流程图一样连线),让整个数据的流向一目了然。组件库非常丰富(特别是对于排序、连接、分组的底层封装很扎实),即使遇到复杂的自定义逻辑,也可以通过内嵌 JS 脚本灵活解决,实现了“零代码为主,低代码为辅”的完美结合。对于学习商业数据分析的学生或业务人员来说,这是极佳的数据资产沉淀利器。

平台相关信息附录:

  • 平台全称:助睿数智(Uniplore)一站式数据科学实验平台

  • 平台定位:覆盖数据接入、ETL处理、机器学习建模到可视化分析的全链路Agentic零代码数据智能

  • 产品官网:https://www.uniplore.com/

  • 实验平台地址:https://lab.guilian.cn/

Logo

一站式 AI 云服务平台

更多推荐