SQL 数据分析终极指南

数据分析不仅仅是制作图表;它是将原始、混乱的数据转化为可操作的洞察。虽然初学者止步于 GROUP BY,但专业分析师知道 SQL 的真正力量在于数据清理时间序列分析流程建模

专业数据分析师将数据库查询转换为可操作的洞察和可视化

在这份综合指南中,我们将使用一个真实的电商数据集完成一个完整的分析工作流程。我们不仅仅运行查询;我们要解决实际的业务问题。

场景:电商性能评估

想象你是一家在线零售商的首席分析师。你的利益相关者问道:

"我们的用户留存趋势如何?基于最近的消费行为,谁是我们最有价值的客户?"

要回答这个问题,简单的聚合是不够的。我们需要高级技术。

1. 数据清理和准备

现实世界的数据从来都不干净。在分析之前,我们通常需要对数据进行分类或处理缺失值。

使用 CASE 进行数据分箱

连续变量(如价格或年龄)很难汇总。分析师通常使用 CASE 语句将它们"分箱"到类别中。

示例数据(products_binning 表)

product_id product_name price
1 Budget Mouse 15.00
2 Standard Keyboard 75.00
3 Premium Monitor 350.00
4 Budget Headphones 25.00
5 Standard Laptop 899.00

查询示例

sql 复制代码
SELECT 
  product_name, 
  price,
  CASE 
    WHEN price < 50 THEN 'Budget'
    WHEN price BETWEEN 50 AND 200 THEN 'Standard'
    ELSE 'Premium'
  END as price_category
FROM products_binning;

查询结果

product_name price price_category
Budget Mouse 15.00 Budget
Standard Keyboard 75.00 Standard
Premium Monitor 350.00 Premium
Budget Headphones 25.00 Budget
Standard Laptop 899.00 Premium

为什么使用数据分箱

  • 简化分析:将数千个不同的价格点减少到 3-5 个类别
  • 便于可视化:更容易制作柱状图和饼图
  • 业务洞察:帮助识别产品定位策略
  • 客户细分:根据消费水平对客户分组

常见的分箱场景

变量类型 分箱示例
价格 Budget (<50), Standard (50-200), Premium (\>200)
年龄 青年 (18-25), 中年 (26-45), 老年 (46+)
收入 低收入, 中等收入, 高收入
订单金额 小额, 中额, 大额

使用 COALESCE 处理 NULL 值

NULL 值会破坏报告。COALESCE 返回第一个非空值,非常适合设置默认值。

示例

sql 复制代码
SELECT 
  customer_name, 
  COALESCE(phone_number, 'No Phone Provided') as contact_info 
FROM customers;

COALESCE 的常见用途

场景 示例
设置默认值 COALESCE(discount, 0)
合并多个列 COALESCE(mobile_phone, home_phone, work_phone)
处理可选字段 COALESCE(middle_name, '')
避免除零错误 amount / COALESCE(quantity, 1)

2. 时间序列分析

业务随时间发生。分析趋势(环比、同比)可能是分析师最常见的任务。

日期截断和趋势分析

我们通常按月或周聚合数据,而不是查看每日数据。

示例数据(orders_time 表)

order_id order_date amount
1 2023-01-15 250.00
2 2023-01-20 180.00
3 2023-02-05 320.00
4 2023-02-18 450.00
5 2023-03-10 280.00

查询示例

sql 复制代码
SELECT 
  strftime('%Y-%m', order_date) as sales_month,
  SUM(amount) as total_revenue
FROM orders_time
GROUP BY 1
ORDER BY 1;

查询结果

sales_month total_revenue
2023-01 430.00
2023-02 770.00
2023-03 280.00

不同数据库的日期函数

数据库 按月聚合 按周聚合
SQLite strftime('%Y-%m', date_col) strftime('%Y-W%W', date_col)
PostgreSQL DATE_TRUNC('month', date_col) DATE_TRUNC('week', date_col)
MySQL DATE_FORMAT(date_col, '%Y-%m') YEARWEEK(date_col)
SQL Server FORMAT(date_col, 'yyyy-MM') DATEPART(week, date_col)

时间序列分析的关键指标

  • 趋势:数据是上升、下降还是平稳?
  • 季节性:是否有周期性模式?
  • 异常值:哪些数据点不寻常?
  • 增长率:变化的速度有多快?

3. 使用窗口函数的高级分析

这是你从"SQL 用户"升级到"数据分析师"的地方。窗口函数允许你在与当前行相关的一组表行上执行计算。

SQL 窗口函数:展示分区、排名和累计总计用于高级数据分析

累计总计

我们年初至今产生了多少累计收入?

示例数据(daily_sales_window 表)

sales_date daily_revenue
2023-01-01 1000.00
2023-01-02 1500.00
2023-01-03 1200.00
2023-01-04 1800.00

查询示例

sql 复制代码
SELECT 
  sales_date,
  daily_revenue,
  SUM(daily_revenue) OVER (ORDER BY sales_date) as cumulative_revenue
FROM daily_sales_window
ORDER BY sales_date;

查询结果

sales_date daily_revenue cumulative_revenue
2023-01-01 1000.00 1000.00
2023-01-02 1500.00 2500.00
2023-01-03 1200.00 3700.00
2023-01-04 1800.00 5500.00

窗口函数的关键概念

  • OVER 子句:定义窗口的范围
  • ORDER BY:定义行的顺序
  • PARTITION BY:将数据分组
  • 窗口帧:ROWS 或 RANGE

常见的窗口函数应用

函数 用途 示例
SUM() OVER 累计总计 年初至今收入
AVG() OVER 移动平均 7 天移动平均
ROW_NUMBER() 行号 分页
RANK() 排名(有间隙) 排行榜
DENSE_RANK() 排名(无间隙) 成绩排名
LAG() 访问前一行 环比增长
LEAD() 访问后一行 预测

排名和 Top N 分析

每个地区的前 2 名客户是谁?简单的 LIMIT 在这里不起作用,因为我们想要每个组的前 N 名。使用 RANK()ROW_NUMBER()

示例数据(customers_ranking 表)

customer_id customer_name region spent
1 Alice North 5000.00
2 Bob North 3000.00
3 Charlie North 2000.00
4 Diana South 4500.00
5 Eve South 3500.00
6 Frank South 2500.00

查询示例

sql 复制代码
SELECT * FROM (
  SELECT 
    customer_name,
    region,
    spent,
    RANK() OVER (PARTITION BY region ORDER BY spent DESC) as rank
  FROM customers_ranking
)
WHERE rank <= 2;

查询结果

customer_name region spent rank
Alice North 5000.00 1
Bob North 3000.00 2
Diana South 4500.00 1
Eve South 3500.00 2

RANK vs DENSE_RANK vs ROW_NUMBER

函数 并列处理 示例(分数:100, 100, 90)
ROW_NUMBER() 不处理并列 1, 2, 3
RANK() 跳过排名 1, 1, 3
DENSE_RANK() 不跳过排名 1, 1, 2

何时使用哪个函数

  • ROW_NUMBER():需要唯一行号(分页)
  • RANK():需要跳过并列后的排名(奥运会排名)
  • DENSE_RANK():需要连续排名(成绩排名)

4. 使用 CTE 的复杂逻辑

当查询变长时,它们变得难以阅读。CTE(WITH 子句)让你将复杂逻辑分解为可读的步骤。

假设我们想找到"高价值流失客户"------消费超过 $500 但在过去 6 个月内没有购买任何东西的客户。

查询示例

sql 复制代码
WITH CustomerStats AS (
    SELECT 
        customer_id, 
        SUM(amount) as total_spend,
        MAX(order_date) as last_order_date
    FROM orders 
    GROUP BY customer_id
),
ChurnedCustomers AS (
    SELECT * 
    FROM CustomerStats
    WHERE last_order_date < DATE('now', '-6 months')
)
SELECT * 
FROM ChurnedCustomers
WHERE total_spend > 500;

CTE 的优势

  • 可读性:将复杂查询分解为逻辑步骤
  • 可维护性:更容易调试和修改
  • 可重用性:可以在同一查询中多次引用 CTE
  • 协作:团队成员更容易理解

CTE 的常见用途

场景 描述
多步骤计算 先计算中间结果,再进行最终计算
递归查询 处理层次结构数据(组织架构、评论树)
数据清理 先清理数据,再进行分析
复杂过滤 先应用多个过滤条件,再聚合

CTE vs 子查询

特性 CTE 子查询
可读性 ✅ 高 ⚠️ 中等
可重用性 ✅ 可以多次引用 ❌ 不能重用
递归 ✅ 支持 ❌ 不支持
性能 ⚠️ 相似 ⚠️ 相似

5. 环比增长 (MoM)

最后,准确的增长指标通常需要将当前性能与过去性能进行比较。LAG() 允许你访问前一行的数据,而无需自连接。

示例数据(sales_mom 表)

sale_id sales_date amount
1 2023-01-15 10000.00
2 2023-01-20 12000.00
3 2023-02-05 15000.00
4 2023-02-18 14000.00
5 2023-03-10 18000.00

查询示例

sql 复制代码
WITH MonthlySales AS (
  SELECT 
    strftime('%Y-%m', sales_date) as month,
    SUM(amount) as revenue
  FROM sales_mom
  GROUP BY 1
)
SELECT 
  month,
  revenue,
  LAG(revenue) OVER (ORDER BY month) as prev_month_revenue,
  ROUND(100.0 * (revenue - LAG(revenue) OVER (ORDER BY month)) / 
        LAG(revenue) OVER (ORDER BY month), 2) as growth_pct
FROM MonthlySales
ORDER BY month;

查询结果

month revenue prev_month_revenue growth_pct
2023-01 22000.00 NULL NULL
2023-02 29000.00 22000.00 31.82
2023-03 18000.00 29000.00 -37.93

LAG 和 LEAD 的用途

函数 方向 常见用途
LAG() 向前看(前一行) 环比增长、变化检测
LEAD() 向后看(后一行) 预测、趋势分析

增长指标计算

指标 公式 SQL 示例
环比增长 (MoM) (本月 - 上月) / 上月 (revenue - LAG(revenue)) / LAG(revenue)
同比增长 (YoY) (今年 - 去年) / 去年 (revenue - LAG(revenue, 12)) / LAG(revenue, 12)
复合增长率 (CAGR) ((结束值 / 开始值)^(1/年数)) - 1 需要多步计算

最佳实践

  • 使用 COALESCE 处理第一行的 NULL 值
  • 使用 ROUND 格式化百分比
  • 考虑使用 NULLIF 避免除零错误
  • 添加注释说明计算逻辑

总结

SQL 中的数据分析远不止检索行。通过掌握这些模式,你可以直接在数据库中回答复杂的业务问题:

5 大核心技术

  1. 分箱和清理:对数据进行分类以便更好地汇总

    • 使用 CASE 进行数据分箱
    • 使用 COALESCE 处理 NULL 值
  2. 日期计算:理解随时间变化的趋势

    • 日期截断和聚合
    • 不同数据库的日期函数
  3. 窗口函数:计算累计聚合和排名

    • 累计总计
    • 排名和 Top N 分析
    • PARTITION BY 分组计算
  4. CTE:组织复杂逻辑

    • 将查询分解为可读步骤
    • 提高可维护性和协作效率
  5. Lag/Lead:分析增长指标

    • 环比增长计算
    • 同比增长分析

从数据录入到数据分析

这些工具将数据录入 与数据分析区分开来:

数据录入 数据分析
SELECT * FROM table 使用窗口函数计算累计总计
GROUP BY 简单聚合 使用 PARTITION BY 分组排名
手动计算增长率 使用 LAG() 自动计算
复制粘贴到 Excel 直接在 SQL 中完成分析

实际应用场景

这些技术可以应用于:

电商分析

  • 客户细分(RFM 分析)
  • 产品性能分析
  • 购物车放弃率分析

SaaS 产品

  • 用户留存分析
  • 功能使用率分析
  • 订阅流失预测

金融分析

  • 交易趋势分析
  • 风险评估
  • 欺诈检测

营销分析

  • 渠道效果分析
  • 转化漏斗分析
  • A/B 测试结果分析

掌握这些 SQL 数据分析技术,你将能够直接在数据库中回答复杂的业务问题,无需依赖外部工具!


相关文章推荐


本文转载自 www.hisqlboy.com

原文标题:SQL for Data Analysis: The Ultimate Guide

原文链接:https://www.hisqlboy.com/blog/sql-for-data-analysis

原作者:SQL Boy Team

转载日期:2026-02-12

著作权归原作者所有。本文仅用于学习交流,非商业用途。

相关推荐
C#程序员一枚2 小时前
大字段查询性能优化终极方案
sql·c#
SQL必知必会2 小时前
SQL 优化技术精要:让查询飞起来
数据库·sql
少云清2 小时前
【安全测试】5_应用服务器安全性测试 _SQL注入和文件上传漏洞
数据库·sql·安全性测试
H Journey2 小时前
Django 教程
数据库·django·sqlite
eWidget2 小时前
核心业务系统国产化:如何破解 Oracle 迁移中的“重构代价”与“性能瓶颈”?
数据库·oracle·重构·kingbase·数据库平替用金仓·金仓数据库
lhxsir2 小时前
oracle常用命令(DBA)
数据库·oracle·dba
Elastic 中国社区官方博客2 小时前
Elasticsearch 8.17.2 升级到 9.2.4 完整升级过程
大数据·运维·数据库·elasticsearch·搜索引擎·全文检索·运维开发
Re.不晚2 小时前
Redis事务
数据库·redis·php
数据知道2 小时前
PostgreSQL:如何定期验证备份的有效性?(灾备演练)
数据库·postgresql