附20+示例代码与思维导图,轻松应对复杂数据关联
在电商系统中,用户信息存储在users表,订单数据在orders表,商品信息在products表。要分析“每个用户的消费金额”,必须 关联多张表 进行查询。这正是多表查询的核心价值:通过表间关联,挖掘数据深层关系。
关系类型 | 描述 | 示例 |
---|---|---|
一对一 | 一条记录对应另一表的一条记录 | 用户 ↔ 身份证信息 |
一对多 | 一条记录对应另一表的多条记录 | 部门 ↔ 员工 |
多对多 | 通过中间表实现双向一对多关系 | 学生 ↔ 课程(选课表关联) |
SELECT * FROM table1, table2; -- 显式笛卡尔积
SELECT * FROM table1 CROSS JOIN table2; -- 显式交叉连接
结果:table1的每条记录与table2所有记录组合(行数 = m×n)
应用场景:生成测试数据、组合分析
作用:返回两表 匹配成功 的记录
SELECT u.name, o.order_no
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
结果:仅显示有订单的用户
作用:以左表为主,返回 全部左表记录 + 匹配的右表记录
SELECT u.name, o.order_no
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
结果:包含所有用户(无订单显示NULL)
作用:以右表为主,返回 全部右表记录 + 匹配的左表记录
SELECT u.name, o.order_no
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
作用:返回两表 所有记录,无匹配则填充NULL
SELECT u.name, o.order_no
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
⚠️ MySQL不支持,可通过UNION实现:
SELECT * FROM users LEFT JOIN orders ON ...
UNION
SELECT * FROM users RIGHT JOIN orders ON ...;
场景:查询员工的上级领导(同一张表)
SELECT e.name AS employee, m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
场景:查询比平均工资高的员工
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
分类:
类型 | 位置 | 示例 |
---|---|---|
标量子查询 | WHERE/SELECT | SELECT (SELECT ...) |
列子查询 | IN/NOT IN | WHERE id IN (SELECT ...) |
行子查询 | 比较运算符 | WHERE (a, b) = (SELECT a, b ...) |
表子查询 | FROM/JOIN | FROM (SELECT ...) AS t |
作用:合并多个SELECT结果(去重)
SELECT name FROM employees
UNION
SELECT name FROM contractors;
UNION ALL:保留重复记录
要求:列数、类型必须一致
场景 | 建议索引 | 示例 |
---|---|---|
JOIN条件字段 | 联合索引 | ALTER TABLE orders ADD INDEX idx_user (user_id); |
WHERE筛选字段 | 单列索引 | ALTER TABLE products ADD INDEX idx_price (price); |
排序/分组字段 | 索引覆盖 | CREATE INDEX idx_name_age ON users(name, age); |
EXPLAIN SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.age > 30;
关键字段:
低效写法:
SELECT * FROM orders
ORDER BY create_time
LIMIT 1000000, 10; -- 扫描前100万+10条
优化方案:
SELECT * FROM orders
WHERE id > 1000000 -- 假设id有序
ORDER BY create_time
LIMIT 10;
SELECT
u.id,
u.name,
SUM(o.amount) AS total_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id
ORDER BY total_amount DESC;
SELECT DISTINCT u.*
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
WHERE oi.product_id = 123;
Linus Torvalds 名言:
"优秀的程序员与普通程序员的区别,在于是否能让代码和查询高效运行。"
讨论:你在多表查询中遇到过哪些棘手问题?欢迎分享解决方案!