MySQL 基础与查询
问题
MySQL 的基本 CRUD 操作有哪些?JOIN、子查询怎么用?
答案
CRUD 基础
crud.sql
-- 创建表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
age INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 插入
INSERT INTO users (name, email, age) VALUES ('Alice', 'alice@example.com', 25);
-- 查询
SELECT name, email FROM users WHERE age > 18 ORDER BY created_at DESC LIMIT 10;
-- 更新
UPDATE users SET age = 26 WHERE id = 1;
-- 删除
DELETE FROM users WHERE id = 1;
JOIN 类型
join.sql
-- 订单表
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
amount DECIMAL(10,2),
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- INNER JOIN:只返回两表都有匹配的行
SELECT u.name, o.amount
FROM users u INNER JOIN orders o ON u.id = o.user_id;
-- LEFT JOIN:返回左表所有行(没有订单的用户也返回)
SELECT u.name, COALESCE(SUM(o.amount), 0) AS total
FROM users u LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;
-- 多表 JOIN
SELECT u.name, o.amount, p.name AS product
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id;
常用函数
functions.sql
-- 聚合函数
SELECT COUNT(*), SUM(amount), AVG(amount), MAX(amount), MIN(amount)
FROM orders;
-- 分组 + HAVING
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
HAVING total > 1000;
-- 字符串函数
SELECT CONCAT(first_name, ' ', last_name) AS full_name,
LENGTH(name), UPPER(email)
FROM users;
-- 日期函数
SELECT * FROM orders
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 子查询
SELECT * FROM users
WHERE id IN (
SELECT user_id FROM orders WHERE amount > 1000
);
-- EXISTS
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM orders o WHERE o.user_id = u.id
);
常见面试问题
Q1: WHERE 和 HAVING 的区别?
答案:
WHERE:在分组前过滤,不能用聚合函数HAVING:在分组后过滤,可以用聚合函数
SELECT user_id, SUM(amount)
FROM orders
WHERE amount > 10 -- 先过滤金额 > 10 的订单
GROUP BY user_id
HAVING SUM(amount) > 1000; -- 再过滤总金额 > 1000 的用户
Q2: UNION 和 UNION ALL 的区别?
答案:
UNION:合并结果并去重(多一次排序操作)UNION ALL:合并结果不去重(性能更好)
Q3: SQL 的执行顺序?
答案:
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
这就是为什么 WHERE 不能用 SELECT 中的别名,但 ORDER BY 可以。
Q4: DELETE、TRUNCATE、DROP 的区别?
答案:
| 操作 | DELETE | TRUNCATE | DROP |
|---|---|---|---|
| 类型 | DML | DDL | DDL |
| 删除内容 | 数据(可条件删除) | 全部数据 | 表 + 数据 |
| 事务 | 支持回滚 | 不可回滚 | 不可回滚 |
| 速度 | 慢(逐行删除) | 快 | 最快 |
| 自增列 | 不重置 | 重置 | N/A |
Q5: 子查询和 JOIN 怎么选?
答案:
优先使用 JOIN,因为:
- MySQL 优化器对 JOIN 优化更好
- JOIN 可以使用索引
- 子查询可能产生临时表,性能差