diff --git "a/02 \346\236\227\344\275\263\346\263\275/20230323 \345\244\215\344\271\240\344\275\234\344\270\232.md" "b/02 \346\236\227\344\275\263\346\263\275/20230323 \345\244\215\344\271\240\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..93722ab32c778a06aee12960f7e1976dc83902c3 --- /dev/null +++ "b/02 \346\236\227\344\275\263\346\263\275/20230323 \345\244\215\344\271\240\344\275\234\344\270\232.md" @@ -0,0 +1,499 @@ +# 复习作业 +```mysql +# 创建数据库,并设置字符集 +CREATE DATABASE db4 charset utf8; +# 2 使用数据库 +USE db4; +# 3 创建表结构 创建一个就插入一个表的数据 +-- 创建价格表结构 +CREATE TABLE price ( id INT PRIMARY KEY auto_increment, -- 价格编号 + price DOUBLE -- 水果价格 +);-- 插入价格数据 +INSERT INTO price +VALUES + ( 1, 2.30 ); +INSERT INTO price +VALUES + ( 2, 3.50 ); +INSERT INTO price +VALUES + ( 4, NULL ); +INSERT INTO price +VALUES + ( 3, 5.5 );-- 创建水果表结构 +CREATE TABLE fruit ( + id INT PRIMARY KEY auto_increment,-- 水果编号 + NAME VARCHAR ( 20 ) NOT NULL,-- 水果名称 + price_id INT,-- 价格编号 + FOREIGN KEY ( price_id ) REFERENCES price ( id ) +);-- 插入水果的数据 +INSERT INTO fruit +VALUES + ( 1, '苹果', 1 ); +INSERT INTO fruit +VALUES + ( 2, '橘子', 2 ); +INSERT INTO fruit +VALUES + ( 3, '香蕉', NULL );-- 3.多表查询 +-- 3.1.笛卡尔积 +-- 需求:查询水果和价格信息 +SELECT + * +FROM + fruit a + LEFT JOIN price b ON a.price_id = b.id; +UNION +SELECT + * +FROM + fruit a + RIGHT JOIN price b ON a.price_id = b.id;-- 3.2.内连接 +-- 避免笛卡尔积问题怎么处理? +-- 练习:查询苹果信息,显示苹果id和价格 +-- 分析:在水果表中可以查看苹果id 名字 ,在价格表中可以查看价格和价格id +SELECT + * +FROM + fruit a + INNER JOIN price b ON a.price_id = b.id +WHERE + a.price_id = ( SELECT price_id FROM fruit WHERE NAME = '苹果' );-- 3.3左外连接 +-- 练习:查询所有水果信息和对应价格信息 +-- fruit f 位于left左边,称为左表,左外连接以左表为主 +-- price p 位于left右边,称为右表 +-- f.* :获取fruit水果表中的所有数据 +-- p.price : 获取price价格表的字段price的值 +SELECT + f.*, + p.price +FROM + fruit f + LEFT JOIN price p ON f.price_id = p.id; +SELECT + f.*, + p.price +FROM + price p + LEFT JOIN fruit f ON p.id = f.price_id;-- 练习:查询没有写价格的水果及价格(先查询所有水果的价格信息,再筛选。) +SELECT + f.*, + p.price +FROM + fruit f + LEFT JOIN price p ON f.price_id = p.id +WHERE + p.id IS NULL;-- 3.4右外连接 +-- 练习:使用右外连接查询所有价格对应的水果名称和价格信息, +-- right join 表示右连接 +-- price p 称为右表 右外连接会查询右表即price表的全部数据以及和左表fruit f的交集 +SELECT + f.*, + p.price +FROM + fruit f + RIGHT JOIN price p ON f.price_id = p.id;-- 练习:查询出没有对应水果的价格编号和价格,水果名 +SELECT + f.*, + p.price +FROM + fruit f + RIGHT JOIN price p ON f.price_id = p.id +WHERE + f.id IS NULL;-- 练习:使用左外连接查询价格对应的水果,显示所有价格 +-- 4.子查询 +-- 创建部门表 1 +CREATE TABLE dept ( id INT PRIMARY KEY AUTO_INCREMENT, -- 部门编号 + NAME VARCHAR ( 20 ) -- 部门名称 +); +INSERT INTO dept ( NAME ) +VALUES + ( '开发部' ),( + '市场部' + ),( + '财务部' + );-- 创建员工表 n +CREATE TABLE emp ( + id INT PRIMARY KEY AUTO_INCREMENT, + NAME VARCHAR ( 10 ), + gender CHAR ( 1 ),-- 性别 + salary DOUBLE,-- 工资 + join_date DATE,-- 入职日期 + dept_id INT,-- 部门编号 + FOREIGN KEY ( dept_id ) REFERENCES dept ( id ) +); +INSERT INTO emp ( NAME, gender, salary, join_date, dept_id ) +VALUES + ( '孙悟空', '男', 7200, '2013-02-24', 1 ); +INSERT INTO emp ( NAME, gender, salary, join_date, dept_id ) +VALUES + ( '猪八戒', '男', 3600, '2010-12-02', 2 ); +INSERT INTO emp ( NAME, gender, salary, join_date, dept_id ) +VALUES + ( '唐僧', '男', 9000, '2008-08-08', 2 ); +INSERT INTO emp ( NAME, gender, salary, join_date, dept_id ) +VALUES + ( '白骨精', '女', 5000, '2015-10-07', 3 ); +INSERT INTO emp ( NAME, gender, salary, join_date, dept_id ) +VALUES + ( '蜘蛛精', '女', 4500, '2011-03-14', 1 );-- 1.查询工资最高的员工是谁 +-- 1.1 在emp员工表中查询最高工资 -- 9000 单行单列 +SELECT + MAX( salary ) +FROM + emp;-- 1.2在emp员工表中根据上述查询的最高工资查询员工信息 +SELECT + * +FROM + emp +WHERE + salary = ( SELECT MAX( salary ) FROM emp );-- 2.查询工资小于平均工资的员工有哪些? +SELECT + * +FROM + emp +WHERE + salary < ( SELECT avg( salary ) FROM emp );-- 2.1在emp员工表中查询平均工资 -- 单行单列 5860 +SELECT + avg( salary ) +FROM + emp;-- 2.2在emp员工表中查询小于上述的平均工资查询员工信息 +-- 3.查询工资大于5000的员工,来自于哪些部门,显示部门的名字 +-- 3.1 在员工表emp中查询工资大于5000的员工部门编号 -- 1 2 单列多值 作为子查询的条件使用in +SELECT + dept_id +FROM + emp +WHERE + salary > 5000;-- 3.2在dept部门表中根据上述查询的部门编号查询部门名字 +SELECT + * +FROM + dept +WHERE + id IN ( SELECT dept_id FROM emp WHERE salary > 5000 );-- 4. 查询开发部与财务部所有的员工信息 +-- 4.1 在dept表查询开发部和财务部的部门编号 -- 1 3 多行单列 作为子查询的条件使用in +SELECT + id +FROM + dept +WHERE + NAME = '开发部' + OR NAME = '财务部';-- 4.2在emp员工表中根据上述查询的部门编号查询员工信息 +SELECT + * +FROM + emp +WHERE + dept_id IN ( SELECT id FROM dept WHERE NAME = '开发部' OR NAME = '财务部' );-- 5.查询出2011年以后入职的员工信息,包括部门名称 +-- 5.1在emp表中查询2011年以后入职的员工信息 -- 多行多列,作为子查询一般使用as起别名作为临时表和其他表查询. +SELECT + * +FROM + emp +WHERE + join_date >= '2011'; + -- 5.2 将上述查询的结果作为临时表和dept表关联查询最后查询员工信息和部门名称 + select d.`NAME`,a.* from dept d INNER JOIN (SELECT + * +FROM + emp +WHERE + join_date >= '2011')as a on d.id = a.dept_id; +-- 5.多表练习 子查询 +-- 教师表 +CREATE TABLE teacher ( id INT ( 11 ) PRIMARY KEY auto_increment, -- 教师编号 + NAME VARCHAR ( 20 ) NOT NULL UNIQUE -- 教师姓名 +);-- 学生表 +CREATE TABLE student ( + id INT ( 11 ) PRIMARY KEY auto_increment,-- 学生编号 + NAME VARCHAR ( 20 ) NOT NULL UNIQUE,-- 学生姓名 + city VARCHAR ( 40 ) NOT NULL,-- 学生城市 + age INT -- 学生年龄 + +);-- 课程信息表 +CREATE TABLE course ( + id INT ( 11 ) PRIMARY KEY auto_increment,-- 课编号 + NAME VARCHAR ( 20 ) NOT NULL UNIQUE,-- 课程名称 + teacher_id INT ( 11 ) NOT NULL,-- 教师编号 + FOREIGN KEY ( teacher_id ) REFERENCES teacher ( id ) +);-- 学生选课表 +CREATE TABLE studentcourse ( + student_id INT NOT NULL,-- 学生编号 + course_id INT NOT NULL,-- 课程编号 + score DOUBLE NOT NULL,-- 考试成绩 + FOREIGN KEY ( student_id ) REFERENCES student ( id ), + FOREIGN KEY ( course_id ) REFERENCES course ( id ) +); +INSERT INTO teacher +VALUES + ( NULL, '关羽' ); +INSERT INTO teacher +VALUES + ( NULL, '张飞' ); +INSERT INTO teacher +VALUES + ( NULL, '赵云' ); +INSERT INTO student +VALUES + ( NULL, '小王', '北京', 20 ); +INSERT INTO student +VALUES + ( NULL, '小李', '上海', 18 ); +INSERT INTO student +VALUES + ( NULL, '小周', '北京', 22 ); +INSERT INTO student +VALUES + ( NULL, '小刘', '北京', 21 ); +INSERT INTO student +VALUES + ( NULL, '小张', '上海', 22 ); +INSERT INTO student +VALUES + ( NULL, '小赵', '北京', 17 ); +INSERT INTO student +VALUES + ( NULL, '小蒋', '上海', 23 ); +INSERT INTO student +VALUES + ( NULL, '小韩', '北京', 25 ); +INSERT INTO student +VALUES + ( NULL, '小魏', '上海', 18 ); +INSERT INTO student +VALUES + ( NULL, '小明', '广州', 20 ); +INSERT INTO course +VALUES + ( NULL, '语文', 1 ); +INSERT INTO course +VALUES + ( NULL, '数学', 1 ); +INSERT INTO course +VALUES + ( NULL, '生物', 2 ); +INSERT INTO course +VALUES + ( NULL, '化学', 2 ); +INSERT INTO course +VALUES + ( NULL, '物理', 2 ); +INSERT INTO course +VALUES + ( NULL, '英语', 3 ); +INSERT INTO studentcourse +VALUES + ( 1, 1, 80 ); +INSERT INTO studentcourse +VALUES + ( 1, 2, 90 ); +INSERT INTO studentcourse +VALUES + ( 1, 3, 85 ); +INSERT INTO studentcourse +VALUES + ( 1, 4, 78 ); +INSERT INTO studentcourse +VALUES + ( 2, 2, 53 ); +INSERT INTO studentcourse +VALUES + ( 2, 3, 77 ); +INSERT INTO studentcourse +VALUES + ( 2, 5, 80 ); +INSERT INTO studentcourse +VALUES + ( 3, 1, 71 ); +INSERT INTO studentcourse +VALUES + ( 3, 2, 70 ); +INSERT INTO studentcourse +VALUES + ( 3, 4, 80 ); +INSERT INTO studentcourse +VALUES + ( 3, 5, 65 ); +INSERT INTO studentcourse +VALUES + ( 3, 6, 75 ); +INSERT INTO studentcourse +VALUES + ( 4, 2, 90 ); +INSERT INTO studentcourse +VALUES + ( 4, 3, 80 ); +INSERT INTO studentcourse +VALUES + ( 4, 4, 70 ); +INSERT INTO studentcourse +VALUES + ( 4, 6, 95 ); +INSERT INTO studentcourse +VALUES + ( 5, 1, 60 ); +INSERT INTO studentcourse +VALUES + ( 5, 2, 70 ); +INSERT INTO studentcourse +VALUES + ( 5, 5, 80 ); +INSERT INTO studentcourse +VALUES + ( 5, 6, 69 ); +INSERT INTO studentcourse +VALUES + ( 6, 1, 76 ); +INSERT INTO studentcourse +VALUES + ( 6, 2, 88 ); +INSERT INTO studentcourse +VALUES + ( 6, 3, 87 ); +INSERT INTO studentcourse +VALUES + ( 7, 4, 80 ); +INSERT INTO studentcourse +VALUES + ( 8, 2, 71 ); +INSERT INTO studentcourse +VALUES + ( 8, 3, 58 ); +INSERT INTO studentcourse +VALUES + ( 8, 5, 68 ); +INSERT INTO studentcourse +VALUES + ( 9, 2, 88 ); +INSERT INTO studentcourse +VALUES + ( 10, 1, 77 ); +INSERT INTO studentcourse +VALUES + ( 10, 2, 76 ); +INSERT INTO studentcourse +VALUES + ( 10, 3, 80 ); +INSERT INTO studentcourse +VALUES + ( 10, 4, 85 ); +INSERT INTO studentcourse +VALUES + ( 10, 5, 83 ); + -- 1.查询获得最高分的学生信息。 +-- 1.1 在中间表中查询最高分-- 95 单行单列 +select MAX(score) from studentcourse; +-- 1.2 在中间表中根据上述查询的最高分查询学生id +select student_id from studentcourse where score = (select MAX(score) from studentcourse); +-- 一个班级最高分95,可以有多名学员,结果有可能是多行多列 +-- 2.查询编号是2的课程比编号是1的课程最高成绩高的学生信息。 +-- 2.1在中间表查询课程编号是1的最高分数 -- 80 +select MAX(score) from studentcourse where course_id = 1; +-- 2.2在中间表中查询课程编号是2并且分数大于上述结果的学生编号 -- 多行单列 +select student_id from studentcourse where course_id = 2 and score > (select MAX(score) from studentcourse where course_id = 1); +-- 2.3 在学生表中根据上述查询的学生编号查询学生信息 +select * from student where id in (select student_id from studentcourse where course_id = 2 and score > (select MAX(score) from studentcourse where course_id = 1)); +-- 3.查询编号是2的课程比编号是1的课程最高成绩高的学生姓名和成绩。 +-- 3.1在中间表查询课程编号是1的最高分数 -- 80 +select MAX(score) from studentcourse where course_id = 1 +-- 3.2在中间表中查询课程编号是2并且分数大于上述结果的学生编号和分数 -- 多行多列作为临时表 +select student_id,score from studentcourse where course_id = 2 and score > (select MAX(score) from studentcourse where course_id = 1); +-- 3.3 将上述查询的结果作为临时表 +select a.name,b.score from student a INNER JOIN (select student_id,score from studentcourse where course_id = 2 and score > (select MAX(score) from studentcourse where course_id = 1)) b on a.id = b.student_id; +-- 4.查询每个同学的学号、姓名、选课数、总成绩 +select a.id,a.name,count(b.course_id),sum(b.score) from student a INNER JOIN studentcourse b on a.id = b.student_id GROUP BY a.id; +-- 4.1在中间表中根据学号分组查询学号 选课数 总成绩 -- 多行多列,作为临时表 +-- 4.2将上述查询的结果作为临时表和学生表进行关联查询 +/* + 注意:如果子查询中查询的结果字段是聚合函数,并且最后结果需要使用聚合函数,那么必须使用as给聚合函数的字段起别名 + */-- 6.多表练习 连接查询 +-- 部门表 +CREATE TABLE dept ( id INT PRIMARY KEY PRIMARY KEY, -- 部门id + dname VARCHAR ( 50 ), -- 部门名称 + loc VARCHAR ( 50 ) -- 部门位置 +);-- 添加4个部门 +INSERT INTO dept ( id, dname, loc ) +VALUES + ( 10, '教研部', '北京' ), + ( 20, '学工部', '上海' ), + ( 30, '销售部', '广州' ), + ( 40, '财务部', '深圳' );-- 职务表,职务名称,职务描述 +CREATE TABLE job ( id INT PRIMARY KEY, -- 职务编号 + jname VARCHAR ( 20 ), -- 职务名称 + description VARCHAR ( 50 ) -- 职务简介 +);-- 添加4个职务 +INSERT INTO job ( id, jname, description ) +VALUES + ( 1, '董事长', '管理整个公司,接单' ), + ( 2, '经理', '管理部门员工' ), + ( 3, '销售员', '向客人推销产品' ), + ( 4, '文员', '使用办公软件' );-- 员工表 +CREATE TABLE emp ( + id INT PRIMARY KEY,-- 员工id + ename VARCHAR ( 50 ),-- 员工姓名 + job_id INT,-- 职务id + mgr INT,-- 上级领导 + joindate DATE,-- 入职日期 + salary DECIMAL ( 7, 2 ),-- 工资 + bonus DECIMAL ( 7, 2 ),-- 奖金 + dept_id INT,-- 所在部门编号 + CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY ( job_id ) REFERENCES job ( id ), + CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY ( dept_id ) REFERENCES dept ( id ) +);-- 添加员工 +INSERT INTO emp ( id, ename, job_id, mgr, joindate, salary, bonus, dept_id ) +VALUES + ( 1001, '孙悟空', 4, 1004, '2000-12-17', '8000.00', NULL, 20 ), + ( 1002, '卢俊义', 3, 1006, '2001-02-20', '16000.00', '3000.00', 30 ), + ( 1003, '林冲', 3, 1006, '2001-02-22', '12500.00', '5000.00', 30 ), + ( 1004, '唐僧', 2, 1009, '2001-04-02', '29750.00', NULL, 20 ), + ( 1005, '李逵', 4, 1006, '2001-09-28', '12500.00', '14000.00', 30 ), + ( 1006, '宋江', 2, 1009, '2001-05-01', '28500.00', NULL, 30 ), + ( 1007, '刘备', 2, 1009, '2001-09-01', '24500.00', NULL, 10 ), + ( 1008, '猪八戒', 4, 1004, '2007-04-19', '30000.00', NULL, 20 ), + ( 1009, '罗贯中', 1, NULL, '2001-11-17', '50000.00', NULL, 10 ), + ( 1010, '吴用', 3, 1006, '2001-09-08', '15000.00', '0.00', 30 ), + ( 1011, '沙僧', 4, 1004, '2007-05-23', '11000.00', NULL, 20 ), + ( 1012, '李逵', 4, 1006, '2001-12-03', '9500.00', NULL, 30 ), + ( 1013, '小白龙', 4, 1004, '2001-12-03', '30000.00', NULL, 20 ), + ( 1014, '关羽', 4, 1007, '2002-01-23', '13000.00', NULL, 10 );-- 工资等级表 +CREATE TABLE salarygrade ( grade INT PRIMARY KEY, losalary INT, -- 最低薪资 + hisalary INT -- 最高薪资 +);-- 添加5个工资等级 +INSERT INTO salarygrade ( grade, losalary, hisalary ) +VALUES + ( 1, 7000, 12000 ), + ( 2, 12010, 14000 ), + ( 3, 14010, 20000 ), + ( 4, 20010, 30000 ), + ( 5, 30010, 99990 ); + -- 1.查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述。 +-- 1.1 确定几张表关联查询:2张表 emp job +select emp.id,emp.ename,emp.salary,job.jname,job.description from emp,job where emp.job_id=job.id; +-- 1.2 确定连接查询的条件即避免笛卡尔积的条件 emp.job_id = job.id +-- 1.3 确定要查询的结果字段:员工编号,员工姓名,工资,职务名称,职务描述 +-- 2.查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 +-- 2.1 确定几张表关联查询:3张表 emp job dept +select emp.id,emp.ename,emp.salary,job.jname,job.description,dept.dname,dept.loc from emp,job,dept WHERE emp.job_id = job.id and emp.dept_id = dept.id; +-- 2.2 确定连接查询的条件即避免笛卡尔积的条件 emp.job_id = job.id and emp.dept_id=dept.id +-- 2.3 确定要查询的结果字段:员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 +/* + 连接查询规律: + 1.确定几张表关联 + 2.确定连接查询的条件 + 3.确定要查询的结果字段 + 4.如果是n张表关联,那么避免笛卡尔积的条件的个数是:n-1 + */-- 3.查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级。 +-- 1.确定几张表关联 4张表 emp job dept salarygrade +select e.ename,e.salary,j.jname,j.description,d.dname,d.loc,s.grade from emp e,job j,dept d,salarygrade s WHERE e.job_id = j.id and e.dept_id = d.id and e.salary BETWEEN s.losalary and s.hisalary; +-- 2.确定连接查询的条件 :emp.job_id = job.id and emp.dept_id=dept.id +-- 其他条件:e.salary between salarygrade.losalary and salarygrade.hisalary +-- 3.确定要查询的结果字段 +-- 4.查询出每个部门的部门编号、部门名称、部门位置、部门人数 +-- 4.1 在emp表中按照部门编号分组查询部门编号和每个部门人数 +-- 4.2 几张表关联:dept 上述临时表 +-- 4.3 条件 dept.id和临时表的dept_id相等 +-- 4.4 分析查询的结果部门编号、部门名称、部门位置、部门人数 +SELECT d.id,d.dname,d.loc,e.cd 部门人数 from dept d INNER JOIN (select dept_id,count(dept_id) cd from emp GROUP BY dept_id) e on d.id =e.dept_id; +``` +