# MySQL 高级查询
# 子查询
# 1. 基本子查询
-- 在WHERE子句中使用子查询
SELECT *
FROM users
WHERE age > (SELECT AVG(age) FROM users);
-- 在FROM子句中使用子查询
SELECT t.department, AVG(t.salary) as avg_salary
FROM (
SELECT * FROM employees
WHERE status = 'active'
) t
GROUP BY t.department;
# 2. 相关子查询
-- 查找每个部门工资最高的员工
SELECT *
FROM employees e1
WHERE salary = (
SELECT MAX(salary)
FROM employees e2
WHERE e1.department = e2.department
);
# 高级连接
# 1. 自连接
-- 查找所有员工及其管理者
SELECT e1.name as employee, e2.name as manager
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;
# 2. 多表连接
-- 连接多个表
SELECT
c.name as customer,
o.order_date,
p.name as product
FROM customers c
JOIN orders o ON c.id = o.customer_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id;
# 窗口函数
# 1. 排名函数
-- ROW_NUMBER(): 唯一排名
SELECT
name,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) as rank
FROM employees;
-- RANK(): 相同值相同排名,跳过重复的排名
SELECT
name,
salary,
RANK() OVER (ORDER BY salary DESC) as rank
FROM employees;
# 2. 分析函数
-- 计算累计总和
SELECT
date,
amount,
SUM(amount) OVER (ORDER BY date) as running_total
FROM sales;
-- 计算移动平均
SELECT
date,
amount,
AVG(amount) OVER (
ORDER BY date
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) as moving_avg
FROM sales;
# 视图
# 1. 创建视图
-- 创建简单视图
CREATE VIEW employee_summary AS
SELECT
department,
COUNT(*) as employee_count,
AVG(salary) as avg_salary
FROM employees
GROUP BY department;
-- 创建带条件的视图
CREATE VIEW high_salary_employees AS
SELECT *
FROM employees
WHERE salary > 50000;
# 2. 使用视图
-- 查询视图
SELECT * FROM employee_summary;
-- 基于视图创建新视图
CREATE VIEW dept_high_salary AS
SELECT department, COUNT(*) as high_salary_count
FROM high_salary_employees
GROUP BY department;
# 存储过程
# 1. 创建存储过程
-- 简单存储过程
DELIMITER //
CREATE PROCEDURE get_employee_count()
BEGIN
SELECT COUNT(*) FROM employees;
END //
DELIMITER ;
-- 带参数的存储过程
DELIMITER //
CREATE PROCEDURE get_employees_by_dept(
IN dept_name VARCHAR(50)
)
BEGIN
SELECT * FROM employees
WHERE department = dept_name;
END //
DELIMITER ;
# 2. 调用存储过程
-- 调用存储过程
CALL get_employee_count();
-- 使用参数调用
CALL get_employees_by_dept('IT');
# 触发器
-- 创建触发器
CREATE TRIGGER after_employee_insert
AFTER INSERT ON employees
FOR EACH ROW
BEGIN
INSERT INTO audit_log (action, employee_id)
VALUES ('INSERT', NEW.id);
END;
# 事务和锁
-- 事务示例
START TRANSACTION;
UPDATE accounts SET balance = balance - 100
WHERE id = 1;
UPDATE accounts SET balance = balance + 100
WHERE id = 2;
-- 检查余额是否合法
IF (SELECT balance FROM accounts WHERE id = 1) >= 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
-- 使用锁
SELECT * FROM accounts
WHERE id = 1
FOR UPDATE;
# 性能优化
# 1. 索引优化
-- 创建复合索引
CREATE INDEX idx_name_email ON users(name, email);
-- 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM users
WHERE name = 'John' AND email LIKE 'john%';
# 2. 查询优化
-- 使用EXISTS代替IN
SELECT * FROM orders o
WHERE EXISTS (
SELECT 1 FROM customers c
WHERE c.id = o.customer_id
AND c.status = 'active'
);
-- 使用UNION ALL代替UNION
SELECT * FROM sales_2021
UNION ALL
SELECT * FROM sales_2022;
# 最佳实践
使用适当的索引
- 为常用查询条件创建索引
- 避免过度索引
- 定期维护索引
优化查询性能
- 只选择需要的列
- 使用适当的连接类型
- 避免子查询滥用
合理使用存储过程
- 封装复杂业务逻辑
- 提高代码重用性
- 注意维护成本
# 练习题
- 编写复杂的多表查询
- 创建和优化存储过程
- 实现触发器实现业务逻辑
# 下一步
学习数据库优化和性能调优的更多技巧。