今日目标:Shell 脚本进入”模块化”阶段,SQL 能够处理多表关联与复杂统计。今天不只是写代码,而是要彻底理解 “如何通过管道组合多个命令”、“如何编写可复用的函数” 以及 “如何通过联表查询获取关联数据”。这是数据分析的基础。
学习内容 (30 mins)
在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。Shell 进阶 (15 mins)
Shell 进阶 (15 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)捕获
- Shell 函数通过
SQL 高级查询 (15 mins)
SQL 高级查询 (15 mins)
什么是聚合函数?聚合函数对一组值执行计算并返回单个值。它们是数据分析的基础工具。为什么需要聚合函数?
- 统计分析:计算总数、平均值、最大值、最小值
- 数据汇总:将多行数据汇总成一行
- 报表生成:生成各种统计报表
- 业务分析:分析业务指标和趋势
-
COUNT():统计行数
-
SUM():求和
-
AVG():平均值
-
MAX() / MIN():最大值/最小值
-
什么是 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)
Shell 函数与日志处理
编写 常见错误:验证步骤:
03_log_cleaner.sh:任务分解:- 定义带时间戳的日志函数
- 使用函数记录操作日志
- 查找日志文件并记录到文件
- 使用管道和重定向处理数据
-
确保 logs 目录存在(Day 02 已创建):
-
运行脚本:
-
检查输出:
- 应该看到带时间戳的日志信息
- 应该看到找到的日志文件数量
- 应该看到前 5 个日志文件列表
-
检查生成的文件:
-
测试边界情况:
- 删除 logs 目录后运行脚本
- 创建空的 logs 目录后运行脚本
SQL 联表分析
新建 字段类型选择详解:
验证步骤:
orders 表并练习联表查询 03_joins.sql:任务分解:- 创建订单表
- 插入测试数据
- 使用聚合函数统计订单
- 使用 GROUP BY 分组统计
- 使用 LEFT JOIN 联表查询
DECIMAL vs FLOAT vs DOUBLE
DECIMAL vs FLOAT vs DOUBLE
- DECIMAL(10, 2):精确小数,适合金额
- 存储:固定精度,不会丢失精度
- 范围:取决于定义的长度
- 适用:金额、价格等需要精确计算的场景
- FLOAT / DOUBLE:浮点数,有精度损失
- 存储:近似值,可能有精度损失
- 范围:更大
- 适用:科学计算、不需要精确值的场景
- 选择依据:金额必须用 DECIMAL,保证精确性
LEFT JOIN vs INNER JOIN
LEFT JOIN vs INNER JOIN
LEFT JOIN:
- 返回左表所有记录
- 右表没有匹配的用 NULL 填充
- 适用:需要显示所有用户,即使没有订单
- 只返回两表都有匹配的记录
- 没有匹配的记录不显示
- 适用:只需要有订单的用户
COALESCE 函数
COALESCE 函数
作用:返回第一个非 NULL 值语法:
COALESCE(value1, value2, ...)应用场景:- 处理 LEFT JOIN 产生的 NULL 值
- 提供默认值
-
连接 MySQL:
-
执行 SQL 脚本:
或者直接复制粘贴 SQL 语句执行
-
验证表创建:
-
验证数据插入:
-
验证聚合函数:
-
验证 GROUP BY:
-
验证 LEFT JOIN:
拓展任务 (30 mins)
Shell 挑战
任务:学习
grep、awk、sed 的简单组合用法,编写一个脚本统计日志文件中的错误数量。提示:- 使用
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 | Shell 流程控制与 SQL CRUD
下一天: 三剑客优化
Day 04 | Shell 三剑客与 SQL 优化