← 返回《Python 数据分析实战》
📑 查看全课大纲(第 14 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.D绘图 -- mplot3d
  82. 82.D曲线可视化
  83. 83.D散点图可视化
  84. 84.D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 101.实战:通过移动设备行为数据预测性别和年龄

数据库多表连接

约 15 分钟

📺 正在播放小象官方高清录播(支持倍速与清晰度调节)

数据库多表关联分析:INNER JOIN、LEFT JOIN 与高级连接实战

小象实战讲义 · Python数据分析实战

在真实的企业业务系统中,为了避免数据冗余并满足关系数据库规范化设计(范式理论),数据绝不会全部堆砌在单张大表里。例如:用户信息保存在 users 表,订单记录保存在 orders 表,商品明细保存在 products 表,部门配置保存在 departments 表。在进行业务指标分析时,我们需要将分散在多张表中的记录通过关联键(Key)“拼装”连接起来。本节将系统拆解 SQL 中最核心的多表连接(JOIN)机制,深入对比交叉连接、内连接与外连接的底层逻辑,并揭示在 SQLite 中实现右连接的等价转换技巧。

💡 核心导读

  • 多表关联的底层数学模型:理解笛卡尔积(Cartesian Product)与关联条件的集合映射。
  • 三大多表连接模式全景剖析
    • 交叉连接(CROSS JOIN):全排列笛卡尔积;
    • 内连接(INNER JOIN):精准交集匹配;
    • 左外连接(LEFT JOIN):保留主表全量基底,附表无匹配补 NULL
  • SQLite 引擎特性与技巧:针对 SQLite 原生不支持 RIGHT JOIN 的现状,掌握交换主附表顺序的等价实现。
  • 员工与部门多表关联实战:通过 Python 代码构建多表测试环境,演练复杂 JOIN 统计报表。

1. 多表连接的核心类型与集合映射

SQL 连接操作本质上是根据两张(或多张)表之间共同的关联字段(如主键和外键),将多表中的列合并为一张宽表。常见的连接类型如下:

┌─────────────────────────────────────────────────────────────┐
│                    SQL 多表连接三大核心形态                  │
├───────────────────────────────┬─────────────────────────────┤
│  1. 交叉连接 (CROSS JOIN)     │  2. 内连接 (INNER JOIN)     │
│  两表的笛卡尔积 (M × N 行)     │  两表交集:仅保留完全匹配行 │
├───────────────────────────────┴─────────────────────────────┤
│  3. 左外连接 (LEFT OUTER JOIN)                              │
│  保留左表 (表A) 全部记录,右表 (表B) 无匹配字段自动填充 NULL │
└─────────────────────────────────────────────────────────────┘

1.1 交叉连接(CROSS JOIN / 笛卡尔积)

  • 如果表 A 有 $M$ 行记录,表 B 有 $N$ 行记录,交叉连接将生成 $M \times N$ 行全排列记录;
  • 除非需要生成全排列测试用例或矩阵网格,日常分析中应避免无条件的 CROSS JOIN(容易造成行数爆炸)。

1.2 内连接(INNER JOIN)

  • 核心逻辑:仅返回两张表中连接条件完全相等的交集记录;
  • 如果左表的某条记录在右表中找不到对应的关联键,或者右表的记录在左表中无匹配,这两条记录都将被过滤剔除。
  • 标准语法
    SELECT A.col1, B.col2 
    FROM tableA AS A 
    INNER JOIN tableB AS B ON A.foreign_key = B.primary_key;

1.3 左外连接(LEFT JOIN)

  • 核心逻辑:以左表(tableA)为基准,返回左表中的所有记录
  • 如果右表(tableB)中有匹配的记录,则对应展示右表的字段值;如果右表中无匹配,则右表所有字段在结果中均填充为 NULL
  • 业务价值:非常适合用于查找“未产生某种行为的实体”(如:查找注册了但从未下过单的用户、无员工归属的空闲部门)。

SQLite 的特殊情况:早期 SQLite 版本不原生支持 RIGHT JOIN。在实际开发中,如果需要右连接(保留右表全部记录),只需交换两张表的书写顺序,改用 LEFT JOIN 即可实现 100% 等价效果


2. Python 代码实战:构建多表环境并演练核心 JOIN 语法

下面我们通过 Python 内置的 sqlite3 模块,在内存中创建两张典型的业务表:员工表(employees)部门表(departments),并录入包含部分孤立数据(有员工未分配部门,也有部门暂无员工)的测试样本。

# 示例 1:创建多表关联测试环境 (员工表与部门表)

import sqlite3
import pandas as pd

conn = sqlite3.connect(":memory:")
cursor = conn.cursor()

# 1. 创建部门表 (departments)
cursor.execute("""
CREATE TABLE departments (
    dept_id INTEGER PRIMARY KEY,
    dept_name TEXT NOT NULL,
    location TEXT
);
""")

# 2. 创建员工表 (employees)
cursor.execute("""
CREATE TABLE employees (
    emp_id INTEGER PRIMARY KEY,
    emp_name TEXT NOT NULL,
    salary REAL,
    dept_id INTEGER  -- 外键关联 departments.dept_id
);
""")

# 插入部门数据 (注:设计部暂无员工)
departments_data = [
    (1, "研发部", "北京中关村"),
    (2, "市场部", "上海陆家嘴"),
    (3, "设计部", "深圳南山")
]
cursor.executemany("INSERT INTO departments VALUES (?, ?, ?);", departments_data)

# 插入员工数据 (注:赵六暂未分配部门 dept_id=None)
employees_data = [
    (101, "张伟", 16000.0, 1),
    (102, "李娜", 13000.0, 2),
    (103, "王强", 18000.0, 1),
    (104, "刘洋", 12000.0, 2),
    (105, "赵六", 9000.0, None)
]
cursor.executemany("INSERT INTO employees VALUES (?, ?, ?, ?);", employees_data)
conn.commit()
print("✅ 多表测试环境搭建就绪!")

接下来,我们分别执行 INNER JOIN、LEFT JOIN 以及利用 LEFT JOIN 识别未分配部门员工与空闲部门:

# 示例 2:执行内连接与左连接对比,并用 Pandas 输出清晰表格

# 1. 内连接 INNER JOIN (仅返回有部门归属的员工及对应部门信息)
sql_inner = """
SELECT e.emp_id, e.emp_name, e.salary, d.dept_name, d.location
FROM employees AS e
INNER JOIN departments AS d ON e.dept_id = d.dept_id;
"""
df_inner = pd.read_sql_query(sql_inner, conn)
print("\n=== 1. 内连接 INNER JOIN (交集:排除了无部门员工与空闲部门) ===")
print(df_inner)

# 2. 左连接 LEFT JOIN (保留全部员工,无部门员工的部门字段为 None/NaN)
sql_left = """
SELECT e.emp_id, e.emp_name, e.salary, d.dept_name, d.location
FROM employees AS e
LEFT JOIN departments AS d ON e.dept_id = d.dept_id;
"""
df_left = pd.read_sql_query(sql_left, conn)
print("\n=== 2. 左外连接 LEFT JOIN (全量员工底表:赵六的部门显示为 None) ===")
print(df_left)

# 3. 巧用 LEFT JOIN 找出“暂无员工的空闲部门” (以部门表为左表,筛选员工 ID 为 NULL 的记录)
sql_idle_dept = """
SELECT d.dept_id, d.dept_name, d.location
FROM departments AS d
LEFT JOIN employees AS e ON d.dept_id = e.dept_id
WHERE e.emp_id IS NULL;
"""
df_idle_dept = pd.read_sql_query(sql_idle_dept, conn)
print("\n=== 3. 业务洞察:筛选暂无员工配置的空闲部门 ===")
print(df_idle_dept)

conn.close()

📝 动手练一练

  1. 案例分析题:如果你作为电商平台的数据分析师,手头有两张表:users (user_id, user_name)orders (order_id, user_id, amount)。如果产品经理需要一份“平台注册至今但从未产生过任何购买行为的沉睡用户清单”,你应该如何编写 SQL?

    👉 点击查看参考答案

    参考答案: 使用 LEFT JOIN 将用户表作为左表,订单表作为右表,并在 WHERE 条件中筛选右表订单主键为 NULL 的记录:

    SELECT u.user_id, u.user_name
    FROM users AS u
    LEFT JOIN orders AS o ON u.user_id = o.user_id
    WHERE o.order_id IS NULL;
  2. 编程练习:假设你有学生表 students (s_id, name) 和选课表 courses (c_id, s_id, course_name)。请编写一段 Python 脚本,使用 SQLite 建立内存表并插入数据,通过 INNER JOIN 查询打印出每位学生选修的课程名称。

    👉 点击查看参考答案

    参考答案

    import sqlite3
    import pandas as pd
    
    conn = sqlite3.connect(":memory:")
    cursor = conn.cursor()
    
    cursor.execute("CREATE TABLE students (s_id INT, name TEXT);")
    cursor.execute("CREATE TABLE courses (c_id INT, s_id INT, course_name TEXT);")
    
    cursor.executemany("INSERT INTO students VALUES (?, ?);", [(1, "小明"), (2, "小红")])
    cursor.executemany("INSERT INTO courses VALUES (?, ?, ?);", [(101, 1, "Python基础"), (102, 1, "数据分析"), (103, 2, "数据分析")])
    conn.commit()
    
    df_res = pd.read_sql_query("""
        SELECT s.name, c.course_name 
        FROM students s 
        INNER JOIN courses c ON s.s_id = c.s_id;
    """, conn)
    
    print("=== 学生选课明细表 ===")
    print(df_res)
    conn.close()

本章小结

在本节中,我们攻克了 SQL 中最为核心的多表关联分析:

  • 深刻掌握交叉连接(CROSS)、内连接(INNER)与左连接(LEFT)的集合差异;
  • 牢记左外连接在业务分析中的杀手级应用:保留主表全量基底,并通过 WHERE 右表字段 IS NULL 快速发现流失或未履约实体;
  • 掌握在 SQLite 下通过交换主附表位置等价实现右连接的工程技巧。

📋 行动清单

  • 在草稿纸上画出 INNER JOIN 与 LEFT JOIN 的维恩图(Venn Diagram)加深印象。
  • 做好准备,进入下一小节的第 2 章综合压轴大实战:《欧洲职业足球数据库分析》!

—— 小象教研组

配套学习资源与课件
  • 本节课件:数据库多表连接(PDF · 221KB)
    下载
  • 全套课件打包(第1-5章)(ZIP · 12.8MB)
    下载
  • 全套课件打包(第6-8章)(ZIP · 15MB)
    下载
  • 实战数据集:AppleStore 应用商城分析(ZIP · 329KB)
    下载
  • 实战数据集:女性服装电商分析(ZIP · 2.8MB)
    下载
  • Python 数据分析环境搭建指南(PDF · 2MB)
    下载
  • Scrapy 安装教程(PDF · 12.7MB)
    下载
  • 附加实战项目:AppleStore 应用商城数据分析(ZIP · 0.3MB · ipynb + CSV 数据)
    下载
  • 附加实战项目:银行电话营销数据分析(ZIP · 0.4MB · ipynb + CSV 数据)
    下载
  • 附加实战项目:女性服装电商评论数据分析(ZIP · 2.7MB · ipynb + CSV 数据)
    下载
  • 附加实战项目:美国化学学会杂志数据分析(ZIP · 34.2MB · ipynb + SQLite 数据库)
    下载
🎁 免费学习资源

领取《小象 11GB VIP 课件资料包与大厂真题手册》

包含全套实战 Jupyter 源码、清洗后数据集、大厂高频面试真题与专属学员答疑交流群。

  • 完整 Python / 数据分析 Jupyter 实战源码
  • 大厂真实业务数据集与练习题
  • 微信扫码添加课程顾问,免费获取网盘下载链接
微信二维码:扫码添加课程顾问微信扫码添加顾问