一、搭建服务器环境
打开网站下方网站下载小皮面板并下载:小皮面板(phpstudy) - 让天下没有难配的服务器环境!
https://www.xp.cn/

下载安装完成后打开页面如下:

小皮这个工具能帮助你一键快速启动MYSQL服务,
好,接下来我们点击启动pdpstudy,提示信息显示我们的MySQL服务已经启动:

然后点击MySQL管理器,选择MySQL-Front

点击打开本地数据库

即可打开数据库操做页面

二、基础的MySQL语句
1.创建、删除数据库并定义格式
#创建一个名为txt1的数据库(txt1这个数据库原本存在不会报错,不存在创建之)
create database if not exists txt1
#指定字符集为utf8mb4,支持所有Unicode字符(包括表情符号)
character set utf8mb4
#指定字符集的排序规则,utf8mb4_unicode_ci是UTF8MB4字符集的标准排序规则
collate utf8mb4_unicode_ci
#查看MySQL服务器上所有的数据库
show database;
#删除指定数据库
drop database if existe txt1
2.表操作语句
create table if not exists students(
#主键,自动增长
id int auto_increment primary key,
#学生名,非空且唯一
name varchar(20) not null unique,
#年龄,默认值为18
age int default 18,
#性别,枚举类型
gender enum('男', '女')
);
结果:

3.添加字段
#添加字段
alter table students add column phone varchar(20) not null unique;
alter table students add column email varchar(50) not null unique;
结果:

4.修改删除字段
### 6. 修改字段
```sql
-- 修改`users`表的`age`字段,将数据类型改为TINYINT,默认值改为20
ALTER TABLE users MODIFY COLUMN age TINYINT DEFAULT 20;
-- 修改`users`表的`gender`字段名和数据类型
ALTER TABLE users CHANGE COLUMN gender sex VARCHAR(10);
```
**解释:**
- `MODIFY COLUMN`:修改字段的类型、长度、约束等,但不能修改字段名
- `CHANGE COLUMN`:可以同时修改字段名和字段属性
### 7. 删除字段
```sql
-- 删除`users`表的`phone`字段
ALTER TABLE users DROP COLUMN phone;
```
**解释:**
- `DROP COLUMN`:删除字段的关键字
- **警告**:删除字段会永久删除该字段的所有数据,操作需谨慎
5.插入模拟数据
-- students表创建和数据插入脚本(显式指定id值)
-- 1. 先删除已有的students表(如果存在)
DROP TABLE IF EXISTS students;
-- 2. 创建包含所有字段的students表
CREATE TABLE IF NOT EXISTS students(
-- 主键,自动增长
id INT AUTO_INCREMENT PRIMARY KEY,
-- 学生名,非空且唯一
name VARCHAR(20) NOT NULL UNIQUE,
-- 年龄,默认值为18
age INT DEFAULT 18,
-- 性别,枚举类型
gender ENUM('男', '女'),
-- 电话,非空且唯一
phone VARCHAR(20) NOT NULL UNIQUE,
-- 邮箱,非空且唯一
email VARCHAR(50) NOT NULL UNIQUE
);
-- 3. 显式指定id值插入100条模拟数据
INSERT INTO students (id, name, age, gender, phone, email) VALUES
(1, '张三', 18, '男', '13800000001', 'zhangsan@example.com'),
(2, '李四', 19, '女', '13800000002', 'lisi@example.com'),
(3, '王五', 20, '男', '13800000003', 'wangwu@example.com'),
(4, '赵六', 17, '女', '13800000004', 'zhaoliu@example.com'),
(5, '孙七', 21, '男', '13800000005', 'sunqi@example.com'),
(6, '周八', 18, '女', '13800000006', 'zhouba@example.com'),
(7, '吴九', 19, '男', '13800000007', 'wujiu@example.com'),
(8, '郑十', 20, '女', '13800000008', 'zhengshi@example.com'),
(9, '陈一', 17, '男', '13800000009', 'chenyi@example.com'),
(10, '林二', 21, '女', '13800000010', 'liner@example.com'),
(11, '黄三', 18, '男', '13800000011', 'huangsan@example.com'),
(12, '杨四', 19, '女', '13800000012', 'yangsi@example.com'),
(13, '赵五', 20, '男', '13800000013', 'zhaowu@example.com'),
(14, '孙六', 17, '女', '13800000014', 'sunliu@example.com'),
(15, '周七', 21, '男', '13800000015', 'zhouqi@example.com'),
(16, '吴八', 18, '女', '13800000016', 'wuba@example.com'),
(17, '郑九', 19, '男', '13800000017', 'zhengjiu@example.com'),
(18, '陈十', 20, '女', '13800000018', 'chenshi@example.com'),
(19, '林一', 17, '男', '13800000019', 'linyi@example.com'),
(20, '黄二', 21, '女', '13800000020', 'huanger@example.com'),
(21, '杨三', 18, '男', '13800000021', 'yangsan@example.com'),
(22, '赵四', 19, '女', '13800000022', 'zhaosi@example.com'),
(23, '孙五', 20, '男', '13800000023', 'sunwu@example.com'),
(24, '周六', 17, '女', '13800000024', 'zhouliu@example.com'),
(25, '吴七', 21, '男', '13800000025', 'wuqi@example.com'),
(26, '郑八', 18, '女', '13800000026', 'zhengba@example.com'),
(27, '陈九', 19, '男', '13800000027', 'chenjiu@example.com'),
(28, '林十', 20, '女', '13800000028', 'linshi@example.com'),
(29, '黄一', 17, '男', '13800000029', 'huangyi@example.com'),
(30, '杨二', 21, '女', '13800000030', 'yang2@example.com'),
(31, '赵三', 18, '男', '13800000031', 'zhaosan@example.com'),
(32, '孙四', 19, '女', '13800000032', 'sunsi@example.com'),
(33, '周五', 20, '男', '13800000033', 'zhouwu@example.com'),
(34, '吴六', 17, '女', '13800000034', 'wuliu@example.com'),
(35, '郑七', 21, '男', '13800000035', 'zhengqi@example.com'),
(36, '陈八', 18, '女', '13800000036', 'chenba@example.com'),
(37, '林九', 19, '男', '13800000037', 'linjiu@example.com'),
(38, '黄十', 20, '女', '13800000038', 'huangshi@example.com'),
(39, '杨一', 17, '男', '13800000039', 'yangyi@example.com'),
(40, '赵二', 21, '女', '13800000040', 'zhaoner@example.com'),
(41, '孙三', 18, '男', '13800000041', 'sunsan@example.com'),
(42, '周四', 19, '女', '13800000042', 'zhousi@example.com'),
(43, '吴五', 20, '男', '13800000043', 'wuwu@example.com'),
(44, '郑六', 17, '女', '13800000044', 'zhengliu@example.com'),
(45, '陈七', 21, '男', '13800000045', 'chenqi@example.com'),
(46, '林八', 18, '女', '13800000046', 'linba@example.com'),
(47, '黄九', 19, '男', '13800000047', 'huangjiu@example.com'),
(48, '杨十', 20, '女', '13800000048', 'yangshi@example.com'),
(49, '赵一', 17, '男', '13800000049', 'zhaoyi@example.com'),
(50, '孙二', 21, '女', '13800000050', 'suner@example.com'),
(51, '周三', 18, '男', '13800000051', 'zhousan@example.com'),
(52, '吴四', 19, '女', '13800000052', 'wusi@example.com'),
(53, '郑五', 20, '男', '13800000053', 'zhengwu@example.com'),
(54, '陈六', 17, '女', '13800000054', 'chenliu@example.com'),
(55, '林七', 21, '男', '13800000055', 'linqi@example.com'),
(56, '黄八', 18, '女', '13800000056', 'huangba@example.com'),
(57, '杨九', 19, '男', '13800000057', 'yangjiu@example.com'),
(58, '赵十', 20, '女', '13800000058', 'zhaoshi@example.com'),
(59, '孙一', 17, '男', '13800000059', 'sunyi@example.com'),
(60, '周二', 21, '女', '13800000060', 'zhouer@example.com'),
(61, '吴三', 18, '男', '13800000061', 'wusan@example.com'),
(62, '郑四', 19, '女', '13800000062', 'zhengsi@example.com'),
(63, '陈五', 20, '男', '13800000063', 'chenwu@example.com'),
(64, '林六', 17, '女', '13800000064', 'linliu@example.com'),
(65, '黄七', 21, '男', '13800000065', 'huangqi@example.com'),
(66, '杨八', 18, '女', '13800000066', 'yangba@example.com'),
(67, '赵九', 19, '男', '13800000067', 'zhaojiu@example.com'),
(68, '孙十', 20, '女', '13800000068', 'sunshi@example.com'),
(69, '周一', 17, '男', '13800000069', 'zhouyi@example.com'),
(70, '吴二', 21, '女', '13800000070', 'wu2@example.com'),
(71, '郑三', 18, '男', '13800000071', 'zhengsan@example.com'),
(72, '陈四', 19, '女', '13800000072', 'chensi@example.com'),
(73, '林五', 20, '男', '13800000073', 'linwu@example.com'),
(74, '黄六', 17, '女', '13800000074', 'huangliu@example.com'),
(75, '杨七', 21, '男', '13800000075', 'yangqi@example.com'),
(76, '赵八', 18, '女', '13800000076', 'zhaoba@example.com'),
(77, '孙九', 19, '男', '13800000077', 'sunjiu@example.com'),
(78, '周十', 20, '女', '13800000078', 'zhoushi@example.com'),
(79, '吴一', 17, '男', '13800000079', 'wuyi@example.com'),
(80, '郑二', 21, '女', '13800000080', 'zhenger@example.com'),
(81, '陈三', 18, '男', '13800000081', 'chensan@example.com'),
(82, '林四', 19, '女', '13800000082', 'linsi@example.com'),
(83, '黄五', 20, '男', '13800000083', 'huangwu@example.com'),
(84, '杨六', 17, '女', '13800000084', 'yangliu@example.com'),
(85, '赵七', 21, '男', '13800000085', 'zhaoqi@example.com'),
(86, '孙八', 18, '女', '13800000086', 'sunba@example.com'),
(87, '周九', 19, '男', '13800000087', 'zhoujiu@example.com'),
(88, '吴十', 20, '女', '13800000088', 'wushi@example.com'),
(89, '郑一', 17, '男', '13800000089', 'zhengyi@example.com'),
(90, '陈二', 21, '女', '13800000090', 'chener@example.com'),
(91, '林三', 18, '男', '13800000091', 'linsan@example.com'),
(92, '黄四', 19, '女', '13800000092', 'huangsi@example.com'),
(93, '杨五', 20, '男', '13800000093', 'yangwu@example.com'),
(94, '赵六2', 17, '女', '13800000094', 'zhaoliu2@example.com'),
(95, '孙七2', 21, '男', '13800000095', 'sunqi2@example.com'),
(96, '周八2', 18, '女', '13800000096', 'zhouba2@example.com'),
(97, '吴九2', 19, '男', '13800000097', 'wujiu2@example.com'),
(98, '郑十2', 20, '女', '13800000098', 'zhengshi2@example.com'),
(99, '陈一2', 17, '男', '13800000099', 'chenyi2@example.com'),
(100, '林二2', 21, '女', '13800000100', 'liner2@example.com');
-- 4. 验证插入结果
SELECT COUNT(*) AS total_students FROM students;
结果如下:

6.查询(重要重要重要)
单表查询
#查询所有表内数据
select * from students;

#查询表内id和name数据
select id,name from students;

#查询表内id和name数据;
#带条件查询(id前10位)
select id,name from students where id<=10;

#查询表内id和name数据;
#多条件查询(id前10位并且name为张三的)
select id,name from students where id<=10 and name='张三';

#查询表内id和name数据;
#范围查询(BETWEEN和where)
select id,name from students where id>10 and id<20;
select id,name from students where id between 30 and 40;

#枚举查询(IN)
select * from students where name in ('张三','赵四');

#模糊查询like
select * from students where name like '张%';
#张开头
select * from students where name like '%帅';
#帅结尾
select * from students where name like '%中%';
#中在中间的

#按年龄升序排序
select * from students order by age asc;
#按年龄降序排序
select * from students order by age desc;

#限制查询结果数量(LIMIT)
#查询前5条记录
select * from students limit 5;
#从第11条记录开始,查询5条记录
select * from students limit 5 offset 10;

-- 1. 统计学生总数
SELECT COUNT(*) AS total_students FROM students;

-- 2. 计算学生平均年龄
SELECT AVG(age) AS avg_age FROM students;

-- 3. 找出最小和最大年龄
SELECT MIN(age) AS youngest, MAX(age) AS oldest FROM students;

-- 4. 按性别分组统计
SELECT
gender,
COUNT(*) AS count,
AVG(age) AS avg_age,
MIN(age) AS min_age,
MAX(age) AS max_age
FROM students
GROUP BY gender;

select
case
where age<=18 then '未成年'
where age between 18 and 25 then '青年'
else '成年'
end as age_group,
count(*) as count
from student
group by age_group;

-- 6. 筛选分组结果(HAVING)
SELECT
gender,
COUNT(*) AS count
FROM students
GROUP BY gender
HAVING count > 40;
HAVING 子句用于筛选分组后的结果,类似于 WHERE 但作用于分组
HAVING 可以使用聚合函数的别名,而 WHERE 不能
HAVING 必须放在 GROUP BY 子句之后
与 WHERE 的区别: WHERE 筛选的是原始数据行, HAVING 筛选的是分组结果

7.灵活的视图(VIEWS)
视图是虚拟表,基于SQL查询结果创建,不存储实际数据,只存储查询定义。
-- 1. 创建学生基本信息视图
CREATE VIEW v_student_basic AS
SELECT id, name, age, gender FROM students;

-- 使用视图
SELECT * FROM v_student_basic WHERE gender = '男';

-- 2. 创建学生联系方式视图
CREATE VIEW v_student_contact AS
SELECT id, name, phone, email FROM students;

-- 3. 创建学生统计视图
CREATE VIEW v_student_stats AS
SELECT
gender,
COUNT(*) AS total,
AVG(age) AS avg_age
FROM students
GROUP BY gender;

8.约束条件
常用约束
`PRIMARY KEY`:主键约束
`UNIQUE`:唯一约束
`NOT NULL`:非空约束
`DEFAULT`:默认值约束
`FOREIGN KEY`:外键约束
`CHECK`:检查约束
-- 1. 查看students表的约束
DESC students;
SHOW CREATE TABLE students;
-- 2. 添加检查约束(MySQL 8.0+支持)
ALTER TABLE students
ADD CONSTRAINT chk_age CHECK (age BETWEEN 0 AND 100);
-- 3. 修改默认值约束
ALTER TABLE students
ALTER COLUMN age SET DEFAULT 18;
-- 4. 添加唯一约束(如果邮箱不是唯一的)
ALTER TABLE students
ADD CONSTRAINT uq_email UNIQUE (email);
-- 5. 测试约束
INSERT INTO students (name, age) VALUES ('测试', 150); -- 违反CHECK约束
INSERT INTO students (name, email) VALUES ('测试', 'zhangsan@example.com'); -- 违反UNIQUE约束
-- 6. 删除约束
ALTER TABLE students
DROP CONSTRAINT chk_age;
8.触发器
-- 1. 创建日志表用于记录学生数据变化
CREATE TABLE student_logs (
log_id INT AUTO_INCREMENT PRIMARY KEY,
student_id INT,
action VARCHAR(20),
field_changed VARCHAR(50),
old_value VARCHAR(100),
new_value VARCHAR(100),
changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 2. 创建INSERT触发器
DELIMITER //
CREATE TRIGGER trg_student_after_insert
AFTER INSERT ON students
FOR EACH ROW
BEGIN
INSERT INTO student_logs (student_id, action, field_changed, old_value, new_value)
VALUES (NEW.id, 'INSERT', 'ALL', NULL, CONCAT('姓名:', NEW.name, ',年龄:', NEW.age, ',性别:', NEW.gender));
END //
DELIMITER ;
-- 3. 创建UPDATE触发器
DELIMITER //
CREATE TRIGGER trg_student_before_update
BEFORE UPDATE ON students
FOR EACH ROW
BEGIN
IF OLD.age != NEW.age THEN
INSERT INTO student_logs (student_id, action, field_changed, old_value, new_value)
VALUES (OLD.id, 'UPDATE', 'age', OLD.age, NEW.age);
END IF;
IF OLD.name != NEW.name THEN
INSERT INTO student_logs (student_id, action, field_changed, old_value, new_value)
VALUES (OLD.id, 'UPDATE', 'name', OLD.name, NEW.name);
END IF;
END //
DELIMITER ;
-- 4. 创建DELETE触发器
DELIMITER //
CREATE TRIGGER trg_student_before_delete
BEFORE DELETE ON students
FOR EACH ROW
BEGIN
INSERT INTO student_logs (student_id, action, field_changed, old_value, new_value)
VALUES (OLD.id, 'DELETE', 'ALL', CONCAT('姓名:', OLD.name, ',年龄:', OLD.age), NULL);
END //
DELIMITER ;
-- 5. 测试触发器
INSERT INTO students (name, age, gender, phone, email)
VALUES ('测试学生', 20, '男', '13800001001', 'test@example.com');
UPDATE students SET age = 21 WHERE name = '测试学生';
UPDATE students SET name = '测试学生2' WHERE phone = '13800001001';
DELETE FROM students WHERE phone = '13800001001';
-- 查看日志
SELECT * FROM student_logs;
-- 6. 删除触发器
DROP TRIGGER IF EXISTS trg_student_after_insert;
9.关联函数
MySQL 连接详解:左连接、右连接、内连接、外连接
先明确核心概念:连接是通过 "关联字段" 将多个表的数据合并展示的操作,不同连接方式决定了 "哪些数据会被保留"。
一、内连接(INNER JOIN)
1. 语法
sql
SELECT 字段
FROM 表A
INNER JOIN 表B
ON 表A.关联字段 = 表B.关联字段;
(可省略INNER,直接写JOIN)
2. 数据量
只保留表 A 和表 B 中 "关联字段匹配成功" 的记录,无匹配的记录会被过滤。数据量 ≤ 表 A 记录数 × 表 B 记录数(取决于关联字段的重复度)。
3. 数据表达
相当于 "两个表的交集",只显示双方都有对应数据的行。
示例:表 A(用户表):
| user_id | name |
|---|---|
| 1 | 张三 |
| 2 | 李四 |
| 3 | 王五 |
表 B(订单表):
| order_id | user_id | goods |
|---|---|---|
| 101 | 1 | 手机 |
| 102 | 2 | 电脑 |
| 103 | 2 | 耳机 |
内连接结果:
sql
SELECT a.name, b.goods
FROM 表A a
INNER JOIN 表B b ON a.user_id = b.user_id;
| name | goods |
|---|---|
| 张三 | 手机 |
| 李四 | 电脑 |
| 李四 | 耳机 |
二、左连接(LEFT JOIN / LEFT OUTER JOIN)
1. 语法
sql
SELECT 字段
FROM 表A -- 左表
LEFT JOIN 表B -- 右表
ON 表A.关联字段 = 表B.关联字段;
2. 数据量
保留左表的所有记录 ,右表中 "匹配成功" 的记录正常显示;右表无匹配的记录,对应的字段显示NULL。数据量 = 左表记录数 + 右表匹配成功的额外重复记录数(若左表一条记录对应右表多条)。
3. 数据表达
相当于 "左表的全部 + 右表与左表的交集",左表数据不丢失。
示例(基于上面的表 A、表 B):
sql
SELECT a.name, b.goods
FROM 表A a
LEFT JOIN 表B b ON a.user_id = b.user_id;
| name | goods | |
|---|---|---|
| 张三 | 手机 | |
| 李四 | 电脑 | |
| 李四 | 耳机 | |
| 王五 | NULL | -- 左表 "王五" 无订单,右表字段为 NULL |
三、右连接(RIGHT JOIN / RIGHT OUTER JOIN)
1. 语法
sql
SELECT 字段
FROM 表A -- 左表
RIGHT JOIN 表B -- 右表
ON 表A.关联字段 = 表B.关联字段;
2. 数据量
保留右表的所有记录 ,左表中 "匹配成功" 的记录正常显示;左表无匹配的记录,对应的字段显示NULL。数据量 = 右表记录数 + 左表匹配成功的额外重复记录数。
3. 数据表达
相当于 "右表的全部 + 左表与右表的交集",右表数据不丢失。
示例(新增表 B 的订单:order_id=104,user_id=4,goods = 键盘):表 B 新增后:
| order_id | user_id | goods |
|---|---|---|
| 101 | 1 | 手机 |
| 102 | 2 | 电脑 |
| 103 | 2 | 耳机 |
| 104 | 4 | 键盘 |
右连接结果:
sql
SELECT a.name, b.goods
FROM 表A a
RIGHT JOIN 表B b ON a.user_id = b.user_id;
| name | goods | |
|---|---|---|
| 张三 | 手机 | |
| 李四 | 电脑 | |
| 李四 | 耳机 | |
| NULL | 键盘 | -- 右表 "user_id=4" 无用户,左表字段为 NULL |
四、外连接(FULL OUTER JOIN)
1. 语法
MySQL不直接支持FULL OUTER JOIN ,需用 "左连接 + 右连接 + UNION" 模拟:
sql
-- 左连接结果 + 右连接中左表为NULL的部分
SELECT a.name, b.goods
FROM 表A a LEFT JOIN 表B b ON a.user_id = b.user_id
UNION
SELECT a.name, b.goods
FROM 表A a RIGHT JOIN 表B b ON a.user_id = b.user_id
WHERE a.user_id IS NULL;
2. 数据量
保留左表和右表的所有记录 ,无匹配的字段显示NULL。数据量 = 左表记录数 + 右表记录数 - 交集记录数。
3. 数据表达
相当于 "左表 + 右表的并集",双方数据都不丢失。
示例(基于表 A 和新增后的表 B):结果:
| name | goods |
|---|---|
| 张三 | 手机 |
| 李四 | 电脑 |
| 李四 | 耳机 |
| 王五 | NULL |
| NULL | 键盘 |
三、面试习题
选择题
SQL中的"SELECT"语句用于:
A. 插入数据
B. 查询数据
C. 更新数据
D. 删除数据
以下哪个关键字用于从查询结果中去除重复记录?
A. DISTINCT
B. UNIQUE
C. REMOVE
D. DELETE
在SQL中,哪个符号用于表示"任意字符"进行模糊匹配?
A. %
B. *
C. ?
D. _
以下哪个操作符用于连接多个条件判断?
A. AND
B. OR
C. NOT
D. BETWEEN
在SQL中,哪个函数用于计算列的平均值?
A. COUNT()
B. AVG()
C. SUM()
D. MAX()
二、判断题
SQL语句不区分大小写。(对/错)
"WHERE"子句用于指定查询条件。(对/错)
"GROUP BY"子句用于对查询结果进行分组。(对/错)
"HAVING"子句用于对分组后的数据进行筛选。(对/错)
"ORDER BY"子句用于对查询结果进行排序。(对/错)
三、填空题
使用SQL查询"employees"表中所有"age"大于30的员工姓名:
SELECT name__ FROM employees WHERE age > 30;
使用SQL查询"sales"表中销售额("amount")大于5000的记录数量:
SELECT count(*)____ FROM sales WHERE amount > 5000;
使用SQL查询"products"表中价格("price")在100到500之间的产品名称:
SELECT product_name FROM products WHERE price __= 100 AND price 《= 500;
使用SQL查询"orders"表中订单日期("order_date")在2022年1月1日之后的订单ID:
SELECT order_id FROM orders WHERE order_date 》 '2022-01-01';
使用SQL查询"customers"表中城市("city")为"New York"的客户数量:
SELECT COUNT(*) FROM customers WHERE city = 'New York';
四、编程题
创建一个名为"students"的表,包含以下字段:
学号(student_id):整数类型,主键
姓名(name):文本类型
年龄(age):整数类型
专业(major):文本类型
CREATE TABLE students (
student_id INT PRIMARY KEY,
name TEXT,
age INT,
major TEXT
);
向"students"表中插入以下数据:
学号:1,姓名:张三,年龄:20,专业:计算机科学
学号:2,姓名:李四,年龄:22,专业:数据科学
学号:3,姓名:王五,年龄:21,专业:人工智能
INSERT INTO students (student_id, name, age, major) VALUES
(1, '张三', 20, '计算机科学'),
(2, '李四', 22, '数据科学'),
(3, '王五', 21, '人工智能');
查询"students"表中所有年龄大于21岁的学生姓名:
SELECT name FROM students WHERE age > 21;
更新"students"表中学号为2的学生的专业为"机器学习":
UPDATE students SET major = '机器学习' WHERE student_id = 2;
删除"students"表中学号为1的学生记录:
DELETE FROM students WHERE student_id = 1;
#create database company
-- 部门表
CREATE TABLE if not exists departments (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID',
dept_name VARCHAR(50) NOT NULL COMMENT '部门名称',
location VARCHAR(100) COMMENT '部门所在地'
);
-- 员工表
CREATE TABLE if not exists employees (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID',
name VARCHAR(50) NOT NULL COMMENT '员工姓名',
age INT COMMENT '年龄',
dept_id INT COMMENT '所属部门ID',
salary DECIMAL(10,2) COMMENT '薪资',
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
INSERT INTO departments (dept_name, location) VALUES
('销售部', '北京市朝阳区'),
('技术部', '上海市浦东新区'),
('人力资源部', '广州市天河区'),
('财务部', '深圳市南山区'),
('市场部', '杭州市西湖区'),
('行政部', '成都市武侯区');
INSERT INTO employees (name, age, dept_id, salary) VALUES
('张三', 28, 1, 8500.00),
('李四', 32, 1, 9200.00),
('王五', 26, 1, 7800.00),
('赵六', 30, 2, 12500.00),
('孙七', 29, 2, 11800.00),
('周八', 35, 2, 15000.00),
('吴九', 27, 3, 6800.00),
('郑十', 31, 3, 7500.00),
('冯十一', 25, 4, 9500.00),
('陈十二', 33, 4, 10200.00),
('褚十三', 24, 5, 7200.00),
('卫十四', 29, 5, 8000.00),
('蒋十五', 34, 6, 6500.00),
('沈十六', 26, 6, 6200.00);
#题 1:查询所有员工的 姓名、年龄、薪资、所属部门名称(最经典的多表关联需求)
select
a.name as 员工姓名,
a.age as 年龄,
a.salary as 薪资,
b.dept_name as 所属部门名称
from employees a
join departments b
on a.dept_id=b.id
#having where a.salary between 7000 and 10000
#order by a.salary asc
#题 2:查询所有员工的 姓名、部门名称,薪资在 7000~10000 之间,左连接实现 + 薪资升序排序
select
a.name as 员工姓名,
b.dept_name as 部门名称
from employees a
left join departments b
on a.dept_id=b.id
where a.salary between 7000 and 10000
order by a.salary asc
#order by a.salary desc
#题 3:以部门表为左表,查询所有部门的名称、员工人数(包含无员工的部门)
select
dept_name as 部门名称,
count(a.id) 员工人数
from employees a
right join departments b
on a.dept_id=b.id
#on a.id=b.id and a.id is null
group by dept_name
#题 4:查询年龄大于 30 岁的员工 姓名、年龄、部门名称,左连接实现,只展示有部门的员工
select
name as 员工姓名,
age as 年龄,
dept_name as 部门名称
from employees a
left join departments b
on a.dept_id=b.id
where age>30 and a.dept_id is not null