Skip to main content
今日目标:Shell 脚本进入”模块化”阶段,SQL 能够处理多表关联与复杂统计。今天不只是写代码,而是要彻底理解 “如何通过管道组合多个命令”“如何编写可复用的函数” 以及 “如何通过联表查询获取关联数据”。这是数据分析的基础。

学习内容 (30 mins)

在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。
什么是管道?管道(|)是 Linux 最强大的特性之一,它可以将一个命令的输出作为另一个命令的输入,实现命令的组合和串联。为什么管道如此重要?
  • 命令组合:将简单命令组合成复杂操作
  • 数据流处理:像流水线一样处理数据
  • 提高效率:一行命令完成多步操作
  • Unix 哲学:每个命令做好一件事,通过管道组合
管道 (|) 详解
  • 基本语法
    • command1 的输出作为 command2 的输入
    • command2 的输出作为 command3 的输入
    • 数据从左到右流动
  • 实际应用
    • ps aux | grep mysql:查找 MySQL 进程
    • cat file.log | grep ERROR | wc -l:统计错误日志行数
    • ls -la | grep "^-" | awk '{print $9}':列出所有文件名
  • 管道 vs 重定向
    • 管道:命令之间的数据传递
    • 重定向:命令与文件之间的数据传递
重定向详解
  • 输出重定向
    • command > file:覆盖写入文件(如果文件不存在会创建)
    • command >> file:追加写入文件
    • command 2> file:将错误输出重定向到文件
    • command > file 2>&1:将标准输出和错误输出都重定向到文件
  • 输入重定向
    • command < file:从文件读取输入
    • command << EOF:Here Document,多行输入
  • 实际应用
    • echo "text" > file.txt:创建文件并写入内容
    • echo "text" >> file.txt:追加内容到文件
    • grep "error" log.txt > errors.txt:将错误日志保存到文件
函数详解
  • 为什么需要函数?
    • 代码复用:避免重复编写相同代码
    • 模块化:将复杂脚本拆分成小函数
    • 可维护性:修改一处,所有调用处都生效
    • 可读性:函数名就是注释,代码更清晰
  • 函数定义
  • 函数调用
  • 函数参数
  • 返回值
    • Shell 函数通过 return 返回退出码(0-255)
    • 通过 echo 输出返回值,调用者用 $(function_name) 捕获
什么是聚合函数?聚合函数对一组值执行计算并返回单个值。它们是数据分析的基础工具。为什么需要聚合函数?
  • 统计分析:计算总数、平均值、最大值、最小值
  • 数据汇总:将多行数据汇总成一行
  • 报表生成:生成各种统计报表
  • 业务分析:分析业务指标和趋势
聚合函数详解
  • COUNT():统计行数
  • SUM():求和
  • AVG():平均值
  • MAX() / MIN():最大值/最小值
GROUP BY 详解
  • 什么是 GROUP BY?
    • 将数据按照指定字段分组
    • 对每个分组应用聚合函数
    • 每个分组返回一行结果
  • 基本语法
  • 实际应用
  • 注意事项
    • SELECT 中的非聚合字段必须出现在 GROUP BY 中
    • GROUP BY 通常与聚合函数一起使用
联表查询详解
  • 为什么需要联表?
    • 数据分散在多个表中
    • 需要同时获取关联数据
    • 避免数据冗余
  • JOIN 类型
    • INNER JOIN:只返回两表都有匹配的记录
    • LEFT JOIN:返回左表所有记录,右表没有匹配的用 NULL 填充
    • RIGHT JOIN:返回右表所有记录,左表没有匹配的用 NULL 填充
    • FULL JOIN:返回两表所有记录(MySQL 不支持)
  • LEFT JOIN(最常用)
    • 返回所有用户,即使没有订单
    • 没有订单的用户,订单相关字段为 NULL
  • INNER JOIN
    • 只返回有订单的用户
    • 没有订单的用户不会出现在结果中

代码任务 (90 mins)

1

Shell 函数与日志处理

编写 03_log_cleaner.sh任务分解
  1. 定义带时间戳的日志函数
  2. 使用函数记录操作日志
  3. 查找日志文件并记录到文件
  4. 使用管道和重定向处理数据
常见错误
  • log_msg "message" - 函数未定义就调用,会报错
  • function log_msg { ... } - 语法错误,应该是 function log_msg() { ... }
  • find ./logs -name *.log - 通配符未加引号,会被 Shell 展开
  • function log_msg() { ... } - 正确写法
  • find ./logs -name "*.log" - 正确写法
验证步骤
  1. 确保 logs 目录存在(Day 02 已创建):
  2. 运行脚本:
  3. 检查输出:
    • 应该看到带时间戳的日志信息
    • 应该看到找到的日志文件数量
    • 应该看到前 5 个日志文件列表
  4. 检查生成的文件:
  5. 测试边界情况:
    • 删除 logs 目录后运行脚本
    • 创建空的 logs 目录后运行脚本
2

SQL 联表分析

新建 orders 表并练习联表查询 03_joins.sql任务分解
  1. 创建订单表
  2. 插入测试数据
  3. 使用聚合函数统计订单
  4. 使用 GROUP BY 分组统计
  5. 使用 LEFT JOIN 联表查询
字段类型选择详解
  • DECIMAL(10, 2):精确小数,适合金额
    • 存储:固定精度,不会丢失精度
    • 范围:取决于定义的长度
    • 适用:金额、价格等需要精确计算的场景
  • FLOAT / DOUBLE:浮点数,有精度损失
    • 存储:近似值,可能有精度损失
    • 范围:更大
    • 适用:科学计算、不需要精确值的场景
  • 选择依据:金额必须用 DECIMAL,保证精确性
LEFT JOIN
  • 返回左表所有记录
  • 右表没有匹配的用 NULL 填充
  • 适用:需要显示所有用户,即使没有订单
INNER JOIN
  • 只返回两表都有匹配的记录
  • 没有匹配的记录不显示
  • 适用:只需要有订单的用户
示例对比
作用:返回第一个非 NULL 值语法COALESCE(value1, value2, ...)应用场景
  • 处理 LEFT JOIN 产生的 NULL 值
  • 提供默认值
示例
验证步骤
  1. 连接 MySQL:
  2. 执行 SQL 脚本:
    或者直接复制粘贴 SQL 语句执行
  3. 验证表创建:
  4. 验证数据插入:
  5. 验证聚合函数:
  6. 验证 GROUP BY:
  7. 验证 LEFT JOIN:
常见错误
  • SELECT user_id, amount FROM orders GROUP BY user_id - amount 未聚合,会报错
  • SELECT * FROM users JOIN orders - 缺少 ON 条件,会产生笛卡尔积
  • INSERT INTO orders (user_id, amount) VALUES (999, 100) - user_id 不存在,外键约束失败
  • SELECT user_id, SUM(amount) FROM orders GROUP BY user_id - 正确
  • SELECT * FROM users u JOIN orders o ON u.id = o.user_id - 正确
  • INSERT INTO orders (user_id, amount) VALUES (1, 100) - 正确(user_id 存在)

拓展任务 (30 mins)

Shell 挑战

任务:学习 grepawksed 的简单组合用法,编写一个脚本统计日志文件中的错误数量。提示
  • 使用 grep "ERROR" log.txt 过滤错误行
  • 使用 awk '{print $2}' 提取第二列
  • 使用 sed 's/old/new/g' 替换文本
  • 思考:如何用管道组合这些命令?

SQL 挑战

任务:学习 HAVING 子句,过滤分组后的数据(如:找出消费总额 > 100 的用户)。提示
  • 使用 HAVING SUM(amount) > 100 过滤分组结果
  • 思考:HAVING 和 WHERE 有什么区别?
  • 什么时候用 WHERE,什么时候用 HAVING?

今日产出物

  • day03/03_log_cleaner.sh - Shell 日志处理脚本
  • day03/03_joins.sql - SQL 联表查询脚本

参考代码

查看参考代码

在 GitHub 查看完整的示例代码

在线运行

使用在线编辑器测试代码

实际应用场景

Shell 管道和函数在运维中的应用

  • 日志分析:使用管道组合 grep、awk、sed 分析日志
  • 数据提取:从命令输出中提取特定信息
  • 批量处理:通过函数封装重复操作,提高代码复用
  • 脚本模块化:将复杂脚本拆分成多个函数,便于维护
  • 错误处理:使用函数统一处理错误和日志输出

SQL 聚合和联表在生产环境的应用

  • 数据统计:使用聚合函数生成各种统计报表
  • 业务分析:通过 GROUP BY 分析业务指标
  • 关联查询:使用 JOIN 获取分散在多个表中的数据
  • 报表生成:结合聚合和联表生成复杂的业务报表
  • 数据分析:为数据分析和决策提供支持
与 Day 02 和 Day 04 的关联
  • Day 02 学习了基础的流程控制和 CRUD,今天学习了如何通过函数和管道组合这些操作
  • Day 04 将学习更高级的文本处理工具(grep/awk/sed),今天的管道知识是基础
  • 掌握今天的函数和联表查询,明天的学习会更轻松

上一天: 流程控制

Day 02 | Shell 流程控制与 SQL CRUD

下一天: 三剑客优化

Day 04 | Shell 三剑客与 SQL 优化