├── 1.查找最晚入职员工的所有信息.md ├── 10.获取所有非manager的员工emp_no.md ├── 11.获取所有员工当前的manager.md ├── 12.获取所有部门中当前员工薪水最高的相关信息.md ├── 13.从titles表获取按照title进行分组.md ├── 14.从titles表获取按照title进行分组2.md ├── 15.查找employees表.md ├── 16.统计出当前各个title类型对应的员工当前薪水对应的平均工资.md ├── 17.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary.md ├── 18.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary2.md ├── 19.查找所有员工的last_name和first_name以及对应的dept_name.md ├── 2.查找入职员工时间排名倒数第三的员工所有信息.md ├── 20.查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth.md ├── 21.查找所有员工自入职以来的薪水涨幅情况.md ├── 22.统计各个部门对应员工涨幅的次数总和.md ├── 23.对所有员工的薪水按照salary进行按照1-N的排名.md ├── 24.获取所有非manager员工当前的薪水情况.md ├── 25.获取员工其当前的薪水比其manager当前薪水还高的相关信息.md ├── 26.汇总各个部门当前员工的title类型的分配数目.md ├── 27.给出每个员工每年薪水涨幅超过5000的员工编号emp_no.md ├── 28.查找描述信息中包括robot的电影对应的分类名称以及电影数目.md ├── 29.使用join查询方式找出没有分类的电影id以及名称.md ├── 3.查找当前薪水详情以及部门编号dept_no.md ├── 30.使用子查询.md ├── 31.获取select对应的执行计划.md ├── 32.将employees表的所有员工的last_name和first_name拼接起来作为Name.md ├── 33.创建一个actor表.md ├── 34.批量插入数据.md ├── 35.批量插入数据不使用replace操作.md ├── 36.创建一个actor_name表.md ├── 37.对first_name创建唯一索引uniq_idx_firstname.md ├── 38.针对actor表创建视图actor_name_view.md ├── 39.针对上面的salaries表emp_no字段创建索引idx_emp_no.md ├── 4.查找所有已经分配部门的员工的last_name和first_name.md ├── 40.在last_update后面新增加一列名字为create_date.md ├── 41.构造一个触发器audit_log.md ├── 42.删除emp_no重复的记录只保留最小的id对应的记录.md ├── 43.将所有to_date为9999-01-01的全部更新为NULL.md ├── 44.将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005.md ├── 45.将titles_test表名修改为titles_2017.md ├── 46.在audit表上创建外键约束其emp_no对应employees_test表的主键id.md ├── 47.如何获取emp_v和employees有相同的数据no.md ├── 48.将所有获取奖金的员工当前的薪水增加10%.md ├── 49.针对库中的所有表生成对应的SQL语句.md ├── 5.查找所有员工的last_name和first_name以及对应部门编号dept_no.md ├── 50.将employees表中的所有员工的last_name和first_name通过连接起来.md ├── 51.查找字符串.md ├── 52.获取Employees中的first_name.md ├── 53.按照dept_no进行汇总.md ├── 54.查找排除当前最大最小salary之后的员工的平均工资avg_salary.md ├── 55.分页查询employees表.md ├── 56.获取所有员工的emp_no.md ├── 57.使用含有关键字exists查找未分配具体部门的员工的所有信息.md ├── 58.获取employees中的行数据且这些行也存在于emp_v中.md ├── 59.获取有奖金的员工相关信息.md ├── 6.查找所有员工入职时候的薪水情况.md ├── 60.统计salary的累计和running_total.md ├── 61.对于employees表中给出奇数行的first_name.md ├── 7.查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t.md ├── 8.找出所有员工当前薪水salary情况.md ├── 9.获取所有部门当前manager的当前薪水情况.md ├── LICENSE └── README.md /1.查找最晚入职员工的所有信息.md: -------------------------------------------------------------------------------- 1 | # 查找最晚入职员工的所有信息 2 | 3 | ## 题目描述 4 | 5 | 查找最晚入职员工的所有信息 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select * from employees where hire_date = (select max(hire_date) from employees); 22 | ``` 23 | 24 | ## 题解 25 | 26 | 由于date数据类型只能精确到天,即可能在最晚的当天存在一个或多个数据,该题使用limit无法获取所有的最晚当天入职的员工信息。 -------------------------------------------------------------------------------- /10.获取所有非manager的员工emp_no.md: -------------------------------------------------------------------------------- 1 | # 获取所有非manager的员工emp_no 2 | 3 | ## 题目描述 4 | 5 | 获取所有非manager的员工emp_no 6 | 7 | ```mysql 8 | CREATE TABLE `dept_manager` ( 9 | `dept_no` char(4) NOT NULL, 10 | `emp_no` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `employees` ( 15 | `emp_no` int(11) NOT NULL, 16 | `birth_date` date NOT NULL, 17 | `first_name` varchar(14) NOT NULL, 18 | `last_name` varchar(16) NOT NULL, 19 | `gender` char(1) NOT NULL, 20 | `hire_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select e.emp_no from employees e where e.emp_no not in (select emp_no from dept_manager) 28 | ``` 29 | 30 | ## 题解 31 | 32 | 将属于manager的所有员工过滤 -------------------------------------------------------------------------------- /11.获取所有员工当前的manager.md: -------------------------------------------------------------------------------- 1 | # 获取所有员工当前的manager 2 | 3 | ## 题目描述 4 | 5 | 获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。 6 | 结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。 7 | 8 | ```mysql 9 | CREATE TABLE `dept_emp` ( 10 | `emp_no` int(11) NOT NULL, 11 | `dept_no` char(4) NOT NULL, 12 | `from_date` date NOT NULL, 13 | `to_date` date NOT NULL, 14 | PRIMARY KEY (`emp_no`,`dept_no`)); 15 | CREATE TABLE `dept_manager` ( 16 | `dept_no` char(4) NOT NULL, 17 | `emp_no` int(11) NOT NULL, 18 | `from_date` date NOT NULL, 19 | `to_date` date NOT NULL, 20 | PRIMARY KEY (`emp_no`,`dept_no`)); 21 | ``` 22 | 23 | ## 答案 24 | 25 | ```mysql 26 | select de.emp_no,dm.emp_no manager_no from dept_emp de left join dept_manager dm on de.dept_no = dm.dept_no where de.to_date= '9999-01-01' and dm.to_date = '9999-01-01' and de.emp_no != dm.emp_no 27 | ``` 28 | 29 | ## 题解 30 | 31 | -------------------------------------------------------------------------------- /12.获取所有部门中当前员工薪水最高的相关信息.md: -------------------------------------------------------------------------------- 1 | # 获取所有部门中当前员工薪水最高的相关信息 2 | 3 | ## 题目描述 4 | 5 | 获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( 9 | `emp_no` int(11) NOT NULL, 10 | `dept_no` char(4) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `salaries` ( 15 | `emp_no` int(11) NOT NULL, 16 | `salary` int(11) NOT NULL, 17 | `from_date` date NOT NULL, 18 | `to_date` date NOT NULL, 19 | PRIMARY KEY (`emp_no`,`from_date`)); 20 | ``` 21 | 22 | ## 答案 23 | 24 | ```mysql 25 | select dept_no,s.emp_no,max(salary) salary from dept_emp de left join salaries s on de.emp_no = s.emp_no where de.to_date = '9999-01-01' and s.to_date = '9999-01-01' group by dept_no having s.salary = max(salary) 26 | ``` 27 | 28 | ## 题解 29 | 30 | -------------------------------------------------------------------------------- /13.从titles表获取按照title进行分组.md: -------------------------------------------------------------------------------- 1 | # 从titles表获取按照title进行分组 2 | 3 | ## 题目描述 4 | 5 | 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS "titles" ( 9 | `emp_no` int(11) NOT NULL, 10 | `title` varchar(50) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date DEFAULT NULL); 13 | ``` 14 | 15 | ## 答案 16 | 17 | ```mysql 18 | select title,count(emp_no) t from titles group by title having count(emp_no) >= 2 19 | ``` 20 | 21 | ## 题解 22 | 23 | -------------------------------------------------------------------------------- /14.从titles表获取按照title进行分组2.md: -------------------------------------------------------------------------------- 1 | # 从titles表获取按照title进行分组,注意对于重复的emp_no进行忽略。 2 | 3 | ## 题目描述 4 | 5 | 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。 6 | 注意对于重复的emp_no进行忽略。 7 | 8 | ```mysql 9 | CREATE TABLE IF NOT EXISTS `titles` ( 10 | `emp_no` int(11) NOT NULL, 11 | `title` varchar(50) NOT NULL, 12 | `from_date` date NOT NULL, 13 | `to_date` date DEFAULT NULL); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select title,count(distinct emp_no) t from titles group by title having t >= 2 20 | ``` 21 | 22 | ## 题解 23 | 24 | -------------------------------------------------------------------------------- /15.查找employees表.md: -------------------------------------------------------------------------------- 1 | # 查找employees表 2 | 3 | ## 题目描述 4 | 5 | 查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列 6 | 7 | ```msyql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select * from employees where last_name != 'Mary' and emp_no % 2 = 1 order by hire_date desc 22 | ``` 23 | 24 | ## 题解 25 | 26 | -------------------------------------------------------------------------------- /16.统计出当前各个title类型对应的员工当前薪水对应的平均工资.md: -------------------------------------------------------------------------------- 1 | # 统计出当前各个title类型对应的员工当前薪水对应的平均工资 2 | 3 | ## 题目描述 4 | 5 | 统计出当前各个title类型对应的员工当前(to_date='9999-01-01')薪水对应的平均工资。结果给出title以及平均工资avg。 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | CREATE TABLE IF NOT EXISTS "titles" ( 15 | `emp_no` int(11) NOT NULL, 16 | `title` varchar(50) NOT NULL, 17 | `from_date` date NOT NULL, 18 | `to_date` date DEFAULT NULL); 19 | ``` 20 | 21 | ## 答案 22 | 23 | ```mysql 24 | select title,avg(salary) avg from titles t left join salaries s on t.emp_no = s.emp_no where t.to_date = '9999-01-01' and s.to_date = '9999-01-01' group by title 25 | ``` 26 | 27 | ## 题解 28 | 29 | 分组聚合 -------------------------------------------------------------------------------- /17.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary.md: -------------------------------------------------------------------------------- 1 | # 获取当前薪水第二多的员工的emp_no以及其对应的薪水salary 2 | 3 | ## 题目描述 4 | 5 | 获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select emp_no,salary from salaries where to_date = '9999-01-01' order by salary desc limit 1,1 20 | ``` 21 | 22 | ## 题解 23 | 24 | -------------------------------------------------------------------------------- /18.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary2.md: -------------------------------------------------------------------------------- 1 | # 获取当前薪水第二多的员工的emp_no以及其对应的薪水salary,不准使用order by 2 | 3 | ## 题目描述 4 | 5 | 查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | CREATE TABLE `salaries` ( 17 | `emp_no` int(11) NOT NULL, 18 | `salary` int(11) NOT NULL, 19 | `from_date` date NOT NULL, 20 | `to_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`,`from_date`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select s.emp_no,salary,last_name,first_name from salaries s left join employees e on e.emp_no = s.emp_no where s.salary = (select max(salary) from salaries where to_date = '9999-01-01' and salary != (select max(salary) from salaries)) 28 | ``` 29 | 30 | ## 题解 31 | 32 | 1、先获得去除了最大值得数据集t1 33 | 34 | 2、再获得t1中的最大值 -------------------------------------------------------------------------------- /19.查找所有员工的last_name和first_name以及对应的dept_name.md: -------------------------------------------------------------------------------- 1 | # 查找所有员工的last_name和first_name以及对应的dept_name 2 | 3 | ## 题目描述 4 | 5 | 查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工 6 | 7 | ```mysql 8 | CREATE TABLE `departments` ( 9 | `dept_no` char(4) NOT NULL, 10 | `dept_name` varchar(40) NOT NULL, 11 | PRIMARY KEY (`dept_no`)); 12 | CREATE TABLE `dept_emp` ( 13 | `emp_no` int(11) NOT NULL, 14 | `dept_no` char(4) NOT NULL, 15 | `from_date` date NOT NULL, 16 | `to_date` date NOT NULL, 17 | PRIMARY KEY (`emp_no`,`dept_no`)); 18 | CREATE TABLE `employees` ( 19 | `emp_no` int(11) NOT NULL, 20 | `birth_date` date NOT NULL, 21 | `first_name` varchar(14) NOT NULL, 22 | `last_name` varchar(16) NOT NULL, 23 | `gender` char(1) NOT NULL, 24 | `hire_date` date NOT NULL, 25 | PRIMARY KEY (`emp_no`)); 26 | ``` 27 | 28 | ## 答案 29 | 30 | ```mysql 31 | select e.last_name,e.first_name,d.dept_name from employees e left join dept_emp de on e.emp_no = de.emp_no left join departments d on de.dept_no = d.dept_no 32 | ``` 33 | 34 | ## 题解 35 | 36 | 三表连接 -------------------------------------------------------------------------------- /2.查找入职员工时间排名倒数第三的员工所有信息.md: -------------------------------------------------------------------------------- 1 | # 查找入职员工时间排名倒数第三的员工所有信息 2 | 3 | ## 题目描述 4 | 5 | 查找入职员工时间排名倒数第三的员工的所有信息 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select * from employees where hire_date = (select distinct hire_date from employees order by hire_date desc limit 2,1) 22 | ``` 23 | 24 | ## 题解 25 | 26 | 与第一题一样,区别在于需要进行去重和排序后获得排名信息。 -------------------------------------------------------------------------------- /20.查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth.md: -------------------------------------------------------------------------------- 1 | # 查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth 2 | 3 | ## 题目描述 4 | 5 | 查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select max(salary) - min(salary) growth from salaries where emp_no = 10001 20 | ``` 21 | 22 | ## 题解 23 | 24 | 简单的减法操作 -------------------------------------------------------------------------------- /21.查找所有员工自入职以来的薪水涨幅情况.md: -------------------------------------------------------------------------------- 1 | # 查找所有员工自入职以来的薪水涨幅情况 2 | 3 | ## 题目描述 4 | 5 | 查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | CREATE TABLE `salaries` ( 17 | `emp_no` int(11) NOT NULL, 18 | `salary` int(11) NOT NULL, 19 | `from_date` date NOT NULL, 20 | `to_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`,`from_date`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select end.emp_no,(end.salary - start.salary) growth from (select emp_no,salary from salaries where to_date = '9999-01-01') end left join (select s.emp_no,salary from salaries s inner join employees e on s.emp_no = e.emp_no where s.from_date = e.hire_date) start on start.emp_no = end.emp_no order by growth 28 | ``` 29 | 30 | ## 题解 31 | 32 | 1、获得当前工资表,放入临时表end中 33 | 34 | ```mysql 35 | -- 目前的工资 36 | (select emp_no,salary from salaries where to_date = '9999-01-01') end 37 | ``` 38 | 39 | 2、获得第一次入职时的工资,放入临时表start中 40 | 41 | ```mysql 42 | -- 最开始的工资 43 | (select s.emp_no,salary from salaries s left join employees e on s.emp_no = e.emp_no where s.from_date = e.hire_date) start 44 | ``` 45 | 46 | 3、连接临时表,用end工资-start工资即可 -------------------------------------------------------------------------------- /22.统计各个部门对应员工涨幅的次数总和.md: -------------------------------------------------------------------------------- 1 | # 统计各个部门对应员工涨幅的次数总和 2 | 3 | ## 题目描述 4 | 5 | 统计各个部门对应员工涨幅的次数总和,给出部门编码dept_no、部门名称dept_name以及次数sum 6 | 7 | ```mysql 8 | CREATE TABLE `departments` ( 9 | `dept_no` char(4) NOT NULL, 10 | `dept_name` varchar(40) NOT NULL, 11 | PRIMARY KEY (`dept_no`)); 12 | CREATE TABLE `dept_emp` ( 13 | `emp_no` int(11) NOT NULL, 14 | `dept_no` char(4) NOT NULL, 15 | `from_date` date NOT NULL, 16 | `to_date` date NOT NULL, 17 | PRIMARY KEY (`emp_no`,`dept_no`)); 18 | CREATE TABLE `salaries` ( 19 | `emp_no` int(11) NOT NULL, 20 | `salary` int(11) NOT NULL, 21 | `from_date` date NOT NULL, 22 | `to_date` date NOT NULL, 23 | PRIMARY KEY (`emp_no`,`from_date`)); 24 | ``` 25 | 26 | ## 答案 27 | 28 | ```mysql 29 | select dept_no,dept_name,sum(sum) sum from (select emp_no,d.dept_no,dept_name from dept_emp de left join departments d on de.dept_no = d.dept_no) info inner join (select emp_no,count(salary) sum from salaries s group by emp_no) s on info.emp_no = s.emp_no group by dept_no 30 | ``` 31 | 32 | ## 题解 33 | 34 | 1、计算每个员工的涨幅次数总和 s 35 | 36 | ```mysql 37 | -- 涨幅次数总和 38 | (select emp_no,count(salary) sum from salaries s group by emp_no) s 39 | ``` 40 | 41 | 2、拼接员工和部门信息 info 42 | 43 | ```mysql 44 | -- 部门信息 45 | (select emp_no,d.dept_no,dept_name from dept_emp de left join departments d on de.dept_no = d.dept_no) info 46 | ``` 47 | 48 | 3、拼接info和s表,对dept_no进行分组,计算每个部门对应的sum总和 49 | 50 | -------------------------------------------------------------------------------- /23.对所有员工的薪水按照salary进行按照1-N的排名.md: -------------------------------------------------------------------------------- 1 | # 对所有员工的薪水按照salary进行按照1-N的排名 2 | 3 | ## 题目描述 4 | 5 | 对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照emp_no升序排列 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select t1.emp_no,t1.salary,count(distinct t2.salary) rank from (select * from salaries s where to_date = '9999-01-01') t1 , (select * from salaries s where to_date = '9999-01-01') t2 where t2.salary >= t1.salary group by t1.emp_no order by rank 20 | ``` 21 | 22 | ## 题解 23 | 24 | 本题无法过MySQL的查询,但是测试通过了sqlite,也就是牛客网提交通过。 25 | 26 | 1、获得两个临时表t1,t2 27 | 28 | ```mysql 29 | (select * from salaries s where to_date = '9999-01-01') t1 30 | (select * from salaries s where to_date = '9999-01-01') t2 31 | ``` 32 | 33 | 2、用第一个临时表的t1.salary去和t2.salary进行比较,从何可以获得所有t1.salary小于t2.salary的数据集,正是如此,我们可以对用户进行分组,统计每个用户对应的salary小于其他用户的数据条数,此为排名。为什么count时要去重,因为可能存在相同排名的人 34 | 35 | ```mysql 36 | select t1.emp_no,count(distinct t2.salary) from t1,t2 where t2.salary >= t1.salary group by t1.emp_no 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /24.获取所有非manager员工当前的薪水情况.md: -------------------------------------------------------------------------------- 1 | # 获取所有非manager员工当前的薪水情况 2 | 3 | ## 题目描述 4 | 5 | 获取所有非manager员工当前的薪水情况,给出dept_no、emp_no以及salary ,当前表示to_date='9999-01-01' 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( 9 | `emp_no` int(11) NOT NULL, 10 | `dept_no` char(4) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `dept_manager` ( 15 | `dept_no` char(4) NOT NULL, 16 | `emp_no` int(11) NOT NULL, 17 | `from_date` date NOT NULL, 18 | `to_date` date NOT NULL, 19 | PRIMARY KEY (`emp_no`,`dept_no`)); 20 | CREATE TABLE `employees` ( 21 | `emp_no` int(11) NOT NULL, 22 | `birth_date` date NOT NULL, 23 | `first_name` varchar(14) NOT NULL, 24 | `last_name` varchar(16) NOT NULL, 25 | `gender` char(1) NOT NULL, 26 | `hire_date` date NOT NULL, 27 | PRIMARY KEY (`emp_no`)); 28 | CREATE TABLE `salaries` ( 29 | `emp_no` int(11) NOT NULL, 30 | `salary` int(11) NOT NULL, 31 | `from_date` date NOT NULL, 32 | `to_date` date NOT NULL, 33 | PRIMARY KEY (`emp_no`,`from_date`)); 34 | ``` 35 | 36 | ## 答案 37 | 38 | ```mysql 39 | select dept_no,s.emp_no,salary from (select * from employees where emp_no not in (select emp_no from dept_manager)) emp, salaries s,dept_emp de where emp.emp_no = s.emp_no and s.to_date = '9999-01-01' and emp.emp_no = de.emp_no 40 | ``` 41 | 42 | ## 题解 43 | 44 | 1、获取所有的manager的no 45 | 46 | ```mysql 47 | select emp_no from dept_manager 48 | ``` 49 | 50 | 2、获取所有非manager的信息表 emp 51 | 52 | ```mysql 53 | select * from employees where emp_no not in (select emp_no from dept_manager) 54 | ``` 55 | 56 | 3、拼接emp,salaries,dept_emp表 获取答案结果集 -------------------------------------------------------------------------------- /25.获取员工其当前的薪水比其manager当前薪水还高的相关信息.md: -------------------------------------------------------------------------------- 1 | # 获取员工其当前的薪水比其manager当前薪水还高的相关信息 2 | 3 | ## 题目描述 4 | 5 | 获取员工其当前的薪水比其manager当前薪水还高的相关信息,当前表示to_date='9999-01-01', 6 | 结果第一列给出员工的emp_no, 7 | 第二列给出其manager的manager_no, 8 | 第三列给出该员工当前的薪水emp_salary, 9 | 第四列给该员工对应的manager当前的薪水manager_salary 10 | 11 | ```mysql 12 | CREATE TABLE `dept_emp` ( 13 | `emp_no` int(11) NOT NULL, 14 | `dept_no` char(4) NOT NULL, 15 | `from_date` date NOT NULL, 16 | `to_date` date NOT NULL, 17 | PRIMARY KEY (`emp_no`,`dept_no`)); 18 | CREATE TABLE `dept_manager` ( 19 | `dept_no` char(4) NOT NULL, 20 | `emp_no` int(11) NOT NULL, 21 | `from_date` date NOT NULL, 22 | `to_date` date NOT NULL, 23 | PRIMARY KEY (`emp_no`,`dept_no`)); 24 | CREATE TABLE `salaries` ( 25 | `emp_no` int(11) NOT NULL, 26 | `salary` int(11) NOT NULL, 27 | `from_date` date NOT NULL, 28 | `to_date` date NOT NULL, 29 | PRIMARY KEY (`emp_no`,`from_date`)); 30 | ``` 31 | 32 | ## 答案 33 | 34 | ```mysql 35 | select t1.emp_no,t2.manager_no,t1.salary emp_salary,t2.manager_salary from (select de.emp_no,salary from dept_emp de,salaries s where de.emp_no not in (select dept_manager.emp_no from dept_manager) and de.emp_no = s.emp_no and s.to_date = '9999-01-01') t1,(select dm.emp_no manager_no,salary manager_salary,dept_no from dept_manager dm,salaries s where dm.emp_no = s.emp_no and s.to_date = '9999-01-01') t2,dept_emp de where t1.emp_no = de.emp_no and de.dept_no = t2.dept_no and t1.salary > manager_salary 36 | ``` 37 | 38 | ## 题解 39 | 40 | 1、获取所有manager的工资信息 t2 41 | 42 | ```mysql 43 | select dm.emp_no manager_no,salary manager_salary,dept_no from dept_manager dm,salaries s where dm.emp_no = s.emp_no and s.to_date = '9999-01-01' 44 | ``` 45 | 46 | 2、获取所有普通员工的工资信息 t1 47 | 48 | ```mysql 49 | select de.emp_no,salary from dept_emp de,salaries s where de.emp_no not in (select dept_manager.emp_no from dept_manager) and de.emp_no = s.emp_no and s.to_date = '9999-01-01' 50 | ``` 51 | 52 | 3、拼接 t1,t2,dept_emp,通过条件过滤 -------------------------------------------------------------------------------- /26.汇总各个部门当前员工的title类型的分配数目.md: -------------------------------------------------------------------------------- 1 | # 汇总各个部门当前员工的title类型的分配数目 2 | 3 | ## 题目描述 4 | 5 | 汇总各个部门当前员工的title类型的分配数目,结果给出部门编号dept_no、dept_name、其当前员工所有的title以及该类型title对应的数目count 6 | 7 | ```mysql 8 | CREATE TABLE `departments` ( 9 | `dept_no` char(4) NOT NULL, 10 | `dept_name` varchar(40) NOT NULL, 11 | PRIMARY KEY (`dept_no`)); 12 | CREATE TABLE `dept_emp` ( 13 | `emp_no` int(11) NOT NULL, 14 | `dept_no` char(4) NOT NULL, 15 | `from_date` date NOT NULL, 16 | `to_date` date NOT NULL, 17 | PRIMARY KEY (`emp_no`,`dept_no`)); 18 | CREATE TABLE IF NOT EXISTS `titles` ( 19 | `emp_no` int(11) NOT NULL, 20 | `title` varchar(50) NOT NULL, 21 | `from_date` date NOT NULL, 22 | `to_date` date DEFAULT NULL); 23 | ``` 24 | 25 | ## 答案 26 | 27 | ```mysql 28 | select d.dept_no,d.dept_name,title,count(emp_no) count from (select emp_no,d.dept_no,title,dept_name from (select de.emp_no,dept_no,title from dept_emp de,titles t where de.emp_no = t.emp_no and t.to_date = '9999-01-01' and de.to_date = '9999-01-01') t1,departments d where t1.dept_no = d.dept_no) t1,departments d where t1.dept_no = d.dept_no group by t1.dept_no,title 29 | ``` 30 | 31 | ## 题解 32 | 33 | 1、当前员工对用的title 34 | 35 | ```mysql 36 | select de.emp_no,dept_no,title from dept_emp de,titles t where de.emp_no = t.emp_no and t.to_date = '9999-01-01' and de.to_date = '9999-01-01' 37 | ``` 38 | 39 | 2、当前员工对应的dept信息 40 | 41 | ```mysql 42 | select emp_no,d.dept_no,title,dept_name from (select de.emp_no,dept_no,title from dept_emp de,titles t where de.emp_no = t.emp_no and t.to_date = '9999-01-01' and de.to_date = '9999-01-01') t1,departments d where t1.dept_no = d.dept_no 43 | ``` 44 | 45 | 3、罗列title对应的count,对dept_no和title进行分组 -------------------------------------------------------------------------------- /27.给出每个员工每年薪水涨幅超过5000的员工编号emp_no.md: -------------------------------------------------------------------------------- 1 | # 给出每个员工每年薪水涨幅超过5000的员工编号emp_no 2 | 3 | ## 题目描述 4 | 5 | 给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。 6 | 7 | 提示:在sqlite中获取datetime时间对应的年份函数为strftime('%Y', to_date) 8 | 9 | ```mysql 10 | CREATE TABLE `salaries` ( 11 | `emp_no` int(11) NOT NULL, 12 | `salary` int(11) NOT NULL, 13 | `from_date` date NOT NULL, 14 | `to_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`,`from_date`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | SELECT s2.emp_no, s2.from_date, (s2.salary - s1.salary) AS salary_growth 22 | FROM salaries AS s1, salaries AS s2 23 | WHERE s1.emp_no = s2.emp_no 24 | AND salary_growth > 5000 25 | AND (strftime("%Y",s2.to_date) - strftime("%Y",s1.to_date) = 1 26 | OR strftime("%Y",s2.from_date) - strftime("%Y",s1.from_date) = 1 ) 27 | ORDER BY salary_growth DESC 28 | ``` 29 | 30 | ## 题解 31 | 32 | -------------------------------------------------------------------------------- /28.查找描述信息中包括robot的电影对应的分类名称以及电影数目.md: -------------------------------------------------------------------------------- 1 | # 查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部 2 | 3 | ## 题目描述 4 | 5 | film表 6 | 7 | | 字段 | 说明 | 8 | | ----------- | ------------ | 9 | | film_id | 电影id | 10 | | title | 电影名称 | 11 | | description | 电影描述信息 | 12 | 13 | ```mysql 14 | CREATE TABLE IF NOT EXISTS film ( 15 | film_id smallint(5) NOT NULL DEFAULT '0', 16 | title varchar(255) NOT NULL, 17 | description text, 18 | PRIMARY KEY (film_id)); 19 | ``` 20 | 21 | category表 22 | 23 | | 字段 | 说明 | 24 | | ----------- | -------------------- | 25 | | category_id | 电影分类id | 26 | | name | 电影分类名称 | 27 | | last_update | 电影分类最后更新时间 | 28 | 29 | ```mysql 30 | CREATE TABLE category ( 31 | category_id tinyint(3) NOT NULL , 32 | name varchar(25) NOT NULL, `last_update` timestamp, 33 | PRIMARY KEY ( category_id )); 34 | ``` 35 | 36 | film_category表 37 | 38 | | 字段 | 说明 | 39 | | ----------- | ------------------------------------ | 40 | | film_id | 电影id | 41 | | category_id | 电影分类id | 42 | | last_update | 电影id和分类id对应关系的最后更新时间 | 43 | 44 | ```mysql 45 | CREATE TABLE film_category ( 46 | film_id smallint(5) NOT NULL, 47 | category_id tinyint(3) NOT NULL, `last_update` timestamp); 48 | ``` 49 | 50 | 查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部 51 | 52 | ## 答案 53 | 54 | ```mysql 55 | select name,count(fc.film_id) from (select fc.category_id,count(f.film_id) ac from film f left join film_category fc on f.film_id = fc.film_id group by category_id having count(f.film_id) >= 5) ac,film f,film_category fc,category c where f.film_id = fc.film_id and fc.category_id = c.category_id and c.category_id = ac.category_id and description like '%robot%'; 56 | ``` 57 | 58 | ## 题解 59 | 60 | 1、获取分类电影数量大于等于5的所有分类ac 61 | 62 | ```mysql 63 | select fc.category_id,count(f.film_id) ac from film f left join film_category fc on f.film_id = fc.film_id group by category_id having count(f.film_id) >= 5; 64 | ``` 65 | 66 | 2、连接ac,film,film_category,category四表 67 | 68 | 3、过滤 -------------------------------------------------------------------------------- /29.使用join查询方式找出没有分类的电影id以及名称.md: -------------------------------------------------------------------------------- 1 | # 使用join查询方式找出没有分类的电影id以及名称 2 | 3 | ## 题目描述 4 | 5 | film表 6 | 7 | | 字段 | 说明 | 8 | | ----------- | ------------ | 9 | | film_id | 电影id | 10 | | title | 电影名称 | 11 | | description | 电影描述信息 | 12 | 13 | ```mysql 14 | CREATE TABLE IF NOT EXISTS film ( 15 | film_id smallint(5) NOT NULL DEFAULT '0', 16 | title varchar(255) NOT NULL, 17 | description text, 18 | PRIMARY KEY (film_id)); 19 | ``` 20 | 21 | category表 22 | 23 | | 字段 | 说明 | 24 | | ----------- | -------------------- | 25 | | category_id | 电影分类id | 26 | | name | 电影分类名称 | 27 | | last_update | 电影分类最后更新时间 | 28 | 29 | ```mysql 30 | CREATE TABLE category ( 31 | category_id tinyint(3) NOT NULL , 32 | name varchar(25) NOT NULL, `last_update` timestamp, 33 | PRIMARY KEY ( category_id )); 34 | ``` 35 | 36 | film_category表 37 | 38 | | 字段 | 说明 | 39 | | ----------- | ------------------------------------ | 40 | | film_id | 电影id | 41 | | category_id | 电影分类id | 42 | | last_update | 电影id和分类id对应关系的最后更新时间 | 43 | 44 | ```mysql 45 | CREATE TABLE film_category ( 46 | film_id smallint(5) NOT NULL, 47 | category_id tinyint(3) NOT NULL, `last_update` timestamp); 48 | ``` 49 | 50 | 使用join查询方式找出没有分类的电影id以及名称 51 | 52 | ## 答案 53 | 54 | ```mysql 55 | select f.film_id,title from film f left join film_category fc on f.film_id = fc.film_id where fc.category_id is null 56 | ``` 57 | 58 | ## 题解 59 | 60 | 1、左连接 61 | 62 | 2、筛选category_id为空的项 -------------------------------------------------------------------------------- /3.查找当前薪水详情以及部门编号dept_no.md: -------------------------------------------------------------------------------- 1 | # 查找当前薪水详情以及部门编号dept_no 2 | 3 | ## 题目描述 4 | 5 | 查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及对应部门编号dept_no 6 | 7 | ```mysql 8 | CREATE TABLE `dept_manager` ( 9 | `dept_no` char(4) NOT NULL, 10 | `emp_no` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | 15 | CREATE TABLE `salaries` ( 16 | `emp_no` int(11) NOT NULL, 17 | `salary` int(11) NOT NULL, 18 | `from_date` date NOT NULL, 19 | `to_date` date NOT NULL, 20 | PRIMARY KEY (`emp_no`,`from_date`)); 21 | ``` 22 | 23 | ## 答案 24 | 25 | ```mysql 26 | select salaries.emp_no,salary,salaries.from_date,salaries.to_date,dept_no from salaries,dept_manager where salaries.emp_no=dept_manager.emp_no and salaries.to_date='9999-01-01' and dept_manager.to_date='9999-01-01' 27 | ``` 28 | 29 | ## 题解 30 | 31 | 简单的多表查询 -------------------------------------------------------------------------------- /30.使用子查询.md: -------------------------------------------------------------------------------- 1 | # 使用子查询的方式找出属于Action分类的所有电影对应的title,description 2 | 3 | ## 题目描述 4 | 5 | film表 6 | 7 | | 字段 | 说明 | 8 | | ----------- | ------------ | 9 | | film_id | 电影id | 10 | | title | 电影名称 | 11 | | description | 电影描述信息 | 12 | 13 | ```mysql 14 | CREATE TABLE IF NOT EXISTS film ( 15 | film_id smallint(5) NOT NULL DEFAULT '0', 16 | title varchar(255) NOT NULL, 17 | description text, 18 | PRIMARY KEY (film_id)); 19 | ``` 20 | 21 | category表 22 | 23 | | 字段 | 说明 | 24 | | ----------- | -------------------- | 25 | | category_id | 电影分类id | 26 | | name | 电影分类名称 | 27 | | last_update | 电影分类最后更新时间 | 28 | 29 | ```mysql 30 | CREATE TABLE category ( 31 | category_id tinyint(3) NOT NULL , 32 | name varchar(25) NOT NULL, `last_update` timestamp, 33 | PRIMARY KEY ( category_id )); 34 | ``` 35 | 36 | film_category表 37 | 38 | | 字段 | 说明 | 39 | | ----------- | ------------------------------------ | 40 | | film_id | 电影id | 41 | | category_id | 电影分类id | 42 | | last_update | 电影id和分类id对应关系的最后更新时间 | 43 | 44 | ```mysql 45 | CREATE TABLE film_category ( 46 | film_id smallint(5) NOT NULL, 47 | category_id tinyint(3) NOT NULL, `last_update` timestamp); 48 | ``` 49 | 50 | 使用子查询的方式找出属于Action分类的所有电影对应的title,description 51 | 52 | ## 答案 53 | 54 | ```mysql 55 | select title,description from film f where exists(select * from film_category fc,category c where fc.category_id = c.category_id and c.name = 'Action' and f.film_id = fc.film_id) 56 | ``` 57 | 58 | ## 题解 59 | 60 | exists子查询操作 -------------------------------------------------------------------------------- /31.获取select对应的执行计划.md: -------------------------------------------------------------------------------- 1 | # 获取 select * from employees 对应的执行计划 2 | 3 | ## 题目描述 4 | 5 | 获取select * from employees对应的执行计划 6 | 7 | ## 答案 8 | 9 | ```mysql 10 | explain select * from employees 11 | ``` 12 | 13 | ## 题解 14 | 15 | explain关键字用于对SQL执行的结果进行分析 16 | 17 | -------------------------------------------------------------------------------- /32.将employees表的所有员工的last_name和first_name拼接起来作为Name.md: -------------------------------------------------------------------------------- 1 | # 将employees表的所有员工的last_name和first_name拼接起来作为Name 2 | 3 | ## 题目描述 4 | 5 | 将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( `emp_no` int(11) NOT NULL, 9 | `birth_date` date NOT NULL, 10 | `first_name` varchar(14) NOT NULL, 11 | `last_name` varchar(16) NOT NULL, 12 | `gender` char(1) NOT NULL, 13 | `hire_date` date NOT NULL, 14 | PRIMARY KEY (`emp_no`)); 15 | ``` 16 | 17 | ## 答案 18 | 19 | ```sqlite 20 | select last_name || " " || first_name Name from employees 21 | ``` 22 | 23 | ## 题解 24 | 25 | MySQL语法: 26 | 27 | ```mysql 28 | select concat(last_name," ",first_name) Name from employees 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /33.创建一个actor表.md: -------------------------------------------------------------------------------- 1 | # 创建一个actor表,包含如下列信息 2 | 3 | ## 题目描述 4 | 5 | 创建一个actor表,包含如下列信息 6 | 7 | 8 | | 列表 | 类型 | 是否为NULL | 含义 | 9 | | :---------- | :---------- | :--------- | :--------------------------------- | 10 | | actor_id | smallint(5) | not null | 主键id | 11 | | first_name | varchar(45) | not null | 名字 | 12 | | last_name | varchar(45) | not null | 姓氏 | 13 | | last_update | timestamp | not null | 最后更新时间,默认是系统的当前时间 | 14 | 15 | ## 答案 16 | 17 | ```mysql 18 | create table actor ( 19 | actor_id smallint(5) not null primary key, 20 | first_name varchar(45) not null, 21 | last_name varchar(45) not null, 22 | last_update timestamp not null default (datetime('now','localtime')) 23 | ) 24 | ``` 25 | 26 | MySQL格式 27 | 28 | ```mysql 29 | create table actor ( 30 | actor_id smallint(5) not null primary key comment '主键id', 31 | first_name varchar(45) not null comment '名字', 32 | last_name varchar(45) not null comment '姓氏', 33 | last_update timestamp not null comment '最后更新时间,默认是系统的当前时间' 34 | ) 35 | ``` 36 | 37 | ## 题解 38 | 39 | 表的创建 -------------------------------------------------------------------------------- /34.批量插入数据.md: -------------------------------------------------------------------------------- 1 | # 批量插入数据 2 | 3 | 对于表actor批量插入如下数据 4 | 5 | ```mysql 6 | CREATE TABLE IF NOT EXISTS actor ( 7 | actor_id smallint(5) NOT NULL PRIMARY KEY, 8 | first_name varchar(45) NOT NULL, 9 | last_name varchar(45) NOT NULL, 10 | last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))) 11 | ``` 12 | 13 | | actor_id | first_name | last_name | last_update | 14 | | :------- | :--------- | :-------- | :------------------ | 15 | | 1 | PENELOPE | GUINESS | 2006-02-15 12:34:33 | 16 | | 2 | NICK | WAHLBERG | 2006-02-15 12:34:33 | 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | insert into actor values (1,'PENELOPE','GUINESS','2006-02-15 12:34:33'),(2,'NICK','WAHLBERG','2006-02-15 12:34:33'); 22 | ``` 23 | 24 | ## 题解 25 | 26 | 简单的插入操作 -------------------------------------------------------------------------------- /35.批量插入数据不使用replace操作.md: -------------------------------------------------------------------------------- 1 | # 批量插入数据,不使用replace操作 2 | 3 | ## 题目描述 4 | 5 | 对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS actor ( 9 | actor_id smallint(5) NOT NULL PRIMARY KEY, 10 | first_name varchar(45) NOT NULL, 11 | last_name varchar(45) NOT NULL, 12 | last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))) 13 | ``` 14 | 15 | | actor_id | first_name | last_name | last_update | 16 | | :------- | :--------- | :-------- | :-------------------- | 17 | | '3' | 'ED' | 'CHASE' | '2006-02-15 12:34:33' | 18 | 19 | ## 答案 20 | 21 | ```sqlite 22 | insert or ignore into actor values (3,'ED','CHASE','2006-02-15 12:34:33'); 23 | ``` 24 | 25 | ## 题解 26 | 27 | MySQL语法: 28 | 29 | ```mysql 30 | insert ignore into actor values (3,'ED','CHASE','2006-02-15 12:34:33'); 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /36.创建一个actor_name表.md: -------------------------------------------------------------------------------- 1 | # 创建一个actor_name表 2 | 3 | ## 题目描述 4 | 5 | 对于如下表actor,其对应的数据为: 6 | 7 | | actor_id | first_name | last_name | last_update | 8 | | :------- | :--------- | :-------- | :------------------ | 9 | | 1 | PENELOPE | GUINESS | 2006-02-15 12:34:33 | 10 | | 2 | NICK | WAHLBERG | 2006-02-15 12:34:33 | 11 | 12 | 创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。 actor_name表结构如下: 13 | 14 | | 列表 | 类型 | 是否为NULL | 含义 | 15 | | :--------- | :---------- | :--------- | :--- | 16 | | first_name | varchar(45) | not null | 名字 | 17 | | last_name | varchar(45) | not null | 姓氏 | 18 | 19 | ## 答案 20 | 21 | ```mysql 22 | create table actor_name ( 23 | first_name varchar(45) not null, 24 | last_name varchar(45) not null 25 | ); 26 | 27 | insert into actor_name select first_name,last_name from actor; 28 | ``` 29 | 30 | ## 题解 31 | 32 | 批量插入 -------------------------------------------------------------------------------- /37.对first_name创建唯一索引uniq_idx_firstname.md: -------------------------------------------------------------------------------- 1 | # 对first_name创建唯一索引uniq_idx_firstname 2 | 3 | ## 题目描述 4 | 5 | 针对如下表actor结构创建索引: 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS actor ( 9 | actor_id smallint(5) NOT NULL PRIMARY KEY, 10 | first_name varchar(45) NOT NULL, 11 | last_name varchar(45) NOT NULL, 12 | last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))) 13 | ``` 14 | 15 | 对first_name创建唯一索引uniq_idx_firstname,对last_name创建普通索引idx_lastname 16 | 17 | ## 答案 18 | 19 | ```mysql 20 | create unique index uniq_idx_firstname on actor(first_name); 21 | create unique index idx_lastname on actor(last_name); 22 | ``` 23 | 24 | ## 题解 25 | 26 | 对于SQLite和MySQL答案通用,但是对于MySQL仍然可以使用alter来进行索引的创建。 27 | 28 | ```mysql 29 | alter table actor add unique index uniq_idx_firstname (first_name),add index idx_lastname (last_name) 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /38.针对actor表创建视图actor_name_view.md: -------------------------------------------------------------------------------- 1 | # 针对actor表创建视图actor_name_view 2 | 3 | ## 题目描述 4 | 5 | 针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v: 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS actor ( 9 | actor_id smallint(5) NOT NULL PRIMARY KEY, 10 | first_name varchar(45) NOT NULL, 11 | last_name varchar(45) NOT NULL, 12 | last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))) 13 | ``` 14 | 15 | ## 答案 16 | 17 | ```mysql 18 | create view actor_name_view as 19 | select first_name first_name_v,last_name last_name_v from actor 20 | ``` 21 | 22 | ## 题解 23 | 24 | 视图创建语句 -------------------------------------------------------------------------------- /39.针对上面的salaries表emp_no字段创建索引idx_emp_no.md: -------------------------------------------------------------------------------- 1 | # 针对上面的salaries表emp_no字段创建索引idx_emp_no 2 | 3 | ## 题目描述 4 | 5 | 针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引。 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | create index idx_emp_no on salaries(emp_no); 15 | ``` 16 | 17 | ## 答案 18 | 19 | ```sqlite 20 | select * from salaries indexed by idx_emp_no where emp_no = 10005; 21 | ``` 22 | 23 | ## 题解 24 | 25 | MySQL语法: 26 | 27 | ```mysql 28 | select * from salaries force index(idx_emp_no) where emp_no = 10005 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /4.查找所有已经分配部门的员工的last_name和first_name.md: -------------------------------------------------------------------------------- 1 | # 查找所有已经分配部门的员工的last_name和first_name 2 | 3 | ## 题目描述 4 | 5 | 查找所有已经分配部门的员工的last_name 和 first_name 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( 9 | `emp_no` int(11) NOT NULL, 10 | `dept_no` char(4) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `employees` ( 15 | `emp_no` int(11) NOT NULL, 16 | `birth_date` date NOT NULL, 17 | `first_name` varchar(14) NOT NULL, 18 | `last_name` varchar(16) NOT NULL, 19 | `gender` char(1) NOT NULL, 20 | `hire_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select last_name,first_name,dept_no from employees inner join dept_emp de on employees.emp_no = de.emp_no 28 | ``` 29 | 30 | ## 题解 31 | 32 | inner join的用法 33 | 34 | -------------------------------------------------------------------------------- /40.在last_update后面新增加一列名字为create_date.md: -------------------------------------------------------------------------------- 1 | # 在last_update后面新增加一列名字为create_date 2 | 3 | ## 题目描述 4 | 5 | 存在actor表,包含如下列信息: 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS actor ( 9 | actor_id smallint(5) NOT NULL PRIMARY KEY, 10 | first_name varchar(45) NOT NULL, 11 | last_name varchar(45) NOT NULL, 12 | last_update timestamp NOT NULL DEFAULT (datetime('now','localtime'))); 13 | ``` 14 | 15 | 现在在last_update后面新增加一列名字为create_date, 类型为datetime, NOT NULL,默认值为'0000-00-00 00:00:00' 16 | 17 | ## 答案 18 | 19 | ```sqlite 20 | alter table actor add column create_date datetime not null default '0000-00-00 00:00:00' 21 | ``` 22 | 23 | ## 题解 24 | 25 | MySQL语法: 26 | 27 | ```mysql 28 | alter table actor add column create_date datetime not null after last_name; 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /41.构造一个触发器audit_log.md: -------------------------------------------------------------------------------- 1 | # 构造一个触发器audit_log 2 | 3 | ## 题目描述 4 | 5 | 构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中。 6 | 7 | ```mysql 8 | CREATE TABLE employees_test( 9 | ID INT PRIMARY KEY NOT NULL, 10 | NAME TEXT NOT NULL, 11 | AGE INT NOT NULL, 12 | ADDRESS CHAR(50), 13 | SALARY REAL 14 | ); 15 | CREATE TABLE audit( 16 | EMP_no INT NOT NULL, 17 | NAME TEXT NOT NULL 18 | ); 19 | ``` 20 | 21 | ## 答案 22 | 23 | ```mysql 24 | create trigger audit_log 25 | after insert 26 | on employees_test 27 | -- for each row 28 | begin 29 | insert into audit values (new.ID,new.NAME); 30 | end; 31 | ``` 32 | 33 | ## 题解 34 | 35 | MySQL语法: 36 | 37 | ```mysql 38 | create trigger audit_log 39 | after insert 40 | on employees_test 41 | for each row 42 | begin 43 | insert into audit values (new.ID,new.NAME); 44 | end; 45 | ``` 46 | 47 | -------------------------------------------------------------------------------- /42.删除emp_no重复的记录只保留最小的id对应的记录.md: -------------------------------------------------------------------------------- 1 | # 删除emp_no重复的记录,只保留最小的id对应的记录。 2 | 3 | ## 题目描述 4 | 5 | 删除emp_no重复的记录,只保留最小的id对应的记录。 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS titles_test ( 9 | id int(11) not null primary key, 10 | emp_no int(11) NOT NULL, 11 | title varchar(50) NOT NULL, 12 | from_date date NOT NULL, 13 | to_date date DEFAULT NULL); 14 | 15 | insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 16 | ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), 17 | ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), 18 | ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), 19 | ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 20 | ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), 21 | ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | delete from titles_test where id not in (select min(t.id) from titles_test t group by t.emp_no) 28 | ``` 29 | 30 | ## 题解 31 | 32 | 1、获取去重后的最小ID临时表 33 | 34 | ```mysql 35 | select min(t.id) from titles_test t group by t.emp_no 36 | ``` 37 | 38 | 2、将不在临时表中的所有数据删除 -------------------------------------------------------------------------------- /43.将所有to_date为9999-01-01的全部更新为NULL.md: -------------------------------------------------------------------------------- 1 | # 将所有to_date为9999-01-01的全部更新为NULL 2 | 3 | ## 题目描述 4 | 5 | 将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS titles_test ( 9 | id int(11) not null primary key, 10 | emp_no int(11) NOT NULL, 11 | title varchar(50) NOT NULL, 12 | from_date date NOT NULL, 13 | to_date date DEFAULT NULL); 14 | 15 | insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 16 | ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), 17 | ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), 18 | ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), 19 | ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 20 | ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), 21 | ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | update titles_test set to_date = null , from_date = '2001-01-01' where to_date = '9999-01-01'; 28 | ``` 29 | 30 | ## 题解 31 | 32 | update的使用 -------------------------------------------------------------------------------- /44.将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005.md: -------------------------------------------------------------------------------- 1 | # 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005 2 | 3 | ## 题目描述 4 | 5 | 将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS titles_test ( 9 | id int(11) not null primary key, 10 | emp_no int(11) NOT NULL, 11 | title varchar(50) NOT NULL, 12 | from_date date NOT NULL, 13 | to_date date DEFAULT NULL); 14 | 15 | insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 16 | ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), 17 | ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), 18 | ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), 19 | ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 20 | ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), 21 | ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | replace into titles_test values ('5', '10005', 'Senior Engineer', '1986-06-26', '9999-01-01') 28 | ``` 29 | 30 | ## 题解 31 | 32 | replace into检测主键或者唯一索引冲突,冲突则替换,否则退化成insert into操作 -------------------------------------------------------------------------------- /45.将titles_test表名修改为titles_2017.md: -------------------------------------------------------------------------------- 1 | # 将titles_test表名修改为titles_2017 2 | 3 | ## 题目描述 4 | 5 | 将titles_test表名修改为titles_2017。 6 | 7 | ```mysql 8 | CREATE TABLE IF NOT EXISTS titles_test ( 9 | id int(11) not null primary key, 10 | emp_no int(11) NOT NULL, 11 | title varchar(50) NOT NULL, 12 | from_date date NOT NULL, 13 | to_date date DEFAULT NULL); 14 | 15 | insert into titles_test values ('1', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 16 | ('2', '10002', 'Staff', '1996-08-03', '9999-01-01'), 17 | ('3', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'), 18 | ('4', '10004', 'Senior Engineer', '1995-12-03', '9999-01-01'), 19 | ('5', '10001', 'Senior Engineer', '1986-06-26', '9999-01-01'), 20 | ('6', '10002', 'Staff', '1996-08-03', '9999-01-01'), 21 | ('7', '10003', 'Senior Engineer', '1995-12-03', '9999-01-01'); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```sqlite 27 | alter table titles_test rename to titles_2017 28 | ``` 29 | 30 | ## 题解 31 | 32 | MySQL语法: 33 | 34 | ```mysql 35 | alter table titles_test rename titles_2017 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /46.在audit表上创建外键约束其emp_no对应employees_test表的主键id.md: -------------------------------------------------------------------------------- 1 | # 在audit表上创建外键约束,其emp_no对应employees_test表的主键id 2 | 3 | ## 题目描述 4 | 5 | 在audit表上创建外键约束,其emp_no对应employees_test表的主键id。 6 | 7 | ```mysql 8 | CREATE TABLE employees_test( 9 | ID INT PRIMARY KEY NOT NULL, 10 | NAME TEXT NOT NULL, 11 | AGE INT NOT NULL, 12 | ADDRESS CHAR(50), 13 | SALARY REAL 14 | ); 15 | 16 | CREATE TABLE audit( 17 | EMP_no INT NOT NULL, 18 | create_date datetime NOT NULL 19 | ); 20 | ``` 21 | 22 | ## 答案 23 | 24 | ```mysql 25 | drop table audit; 26 | 27 | CREATE TABLE audit( 28 | EMP_no INT NOT NULL, 29 | create_date datetime NOT NULL, 30 | FOREIGN KEY(EMP_no) references employees_test(ID)); 31 | ``` 32 | 33 | ## 题解 34 | 35 | MySQL下 36 | 37 | ```mysql 38 | alter table audit add foreign key (EMP_no) references employees_test (ID) 39 | ``` 40 | 41 | 本题在OJ上存在严格的格式限制 -------------------------------------------------------------------------------- /47.如何获取emp_v和employees有相同的数据no.md: -------------------------------------------------------------------------------- 1 | # 如何获取emp_v和employees有相同的数据no 2 | 3 | ## 题目描述 4 | 5 | 存在如下的视图 6 | 7 | ```mysql 8 | create view emp_v as select * from employees where emp_no >10005; 9 | ``` 10 | 11 | 12 | 如何获取emp_v和employees有相同的数据? 13 | 14 | ```mysql 15 | CREATE TABLE `employees` ( 16 | `emp_no` int(11) NOT NULL, 17 | `birth_date` date NOT NULL, 18 | `first_name` varchar(14) NOT NULL, 19 | `last_name` varchar(16) NOT NULL, 20 | `gender` char(1) NOT NULL, 21 | `hire_date` date NOT NULL, 22 | PRIMARY KEY (`emp_no`)); 23 | ``` 24 | 25 | ## 答案 26 | 27 | ```mysql 28 | select e.* from employees e,emp_v ev where e.emp_no = ev.emp_no 29 | ``` 30 | 31 | ## 题解 32 | 33 | 视图的数据源于employees,只需要确保employees.emp_no=emp_v.emp_no即可 -------------------------------------------------------------------------------- /48.将所有获取奖金的员工当前的薪水增加10%.md: -------------------------------------------------------------------------------- 1 | # 将所有获取奖金的员工当前的薪水增加10% 2 | 3 | ## 题目描述 4 | 5 | 将所有获取奖金的员工当前的薪水增加10%。 6 | 7 | ```mysql 8 | create table emp_bonus( 9 | emp_no int not null, 10 | recevied datetime not null, 11 | btype smallint not null); 12 | CREATE TABLE `salaries` ( 13 | `emp_no` int(11) NOT NULL, 14 | `salary` int(11) NOT NULL, 15 | `from_date` date NOT NULL, 16 | `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`from_date`)); 17 | ``` 18 | 19 | ## 答案 20 | 21 | ```mysql 22 | update salaries set salary = salary*1.1 where emp_no in (select emp_no from emp_bonus) 23 | ``` 24 | 25 | ## 题解 26 | 27 | 批量更新操作 -------------------------------------------------------------------------------- /49.针对库中的所有表生成对应的SQL语句.md: -------------------------------------------------------------------------------- 1 | # 针对库中的所有表生成select count(*)对应的SQL语句 2 | 3 | ## 题目描述 4 | 5 | 针对库中的所有表生成select count(*)对应的SQL语句 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | create table emp_bonus( 17 | emp_no int not null, 18 | recevied datetime not null, 19 | btype smallint not null); 20 | CREATE TABLE `dept_emp` ( 21 | `emp_no` int(11) NOT NULL, 22 | `dept_no` char(4) NOT NULL, 23 | `from_date` date NOT NULL, 24 | `to_date` date NOT NULL, 25 | PRIMARY KEY (`emp_no`,`dept_no`)); 26 | CREATE TABLE `dept_manager` ( 27 | `dept_no` char(4) NOT NULL, 28 | `emp_no` int(11) NOT NULL, 29 | `from_date` date NOT NULL, 30 | `to_date` date NOT NULL, 31 | PRIMARY KEY (`emp_no`,`dept_no`)); 32 | CREATE TABLE `salaries` ( 33 | `emp_no` int(11) NOT NULL, 34 | `salary` int(11) NOT NULL, 35 | `from_date` date NOT NULL, 36 | `to_date` date NOT NULL, 37 | PRIMARY KEY (`emp_no`,`from_date`)); 38 | ``` 39 | 40 | ## 答案 41 | 42 | ```sqlite 43 | select "select count(*) from " || name || ";" cnts from sqlite_master where type = "table" 44 | ``` 45 | 46 | ## 题解 47 | 48 | MySQL语法: 49 | 50 | ```mysql 51 | select concat('select count(*) from ',TABLE_NAME,';') cnts from (select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = 'employees') t 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /5.查找所有员工的last_name和first_name以及对应部门编号dept_no.md: -------------------------------------------------------------------------------- 1 | # 查找所有员工的last_name和first_name以及对应部门编号dept_no 2 | 3 | ## 题目描述 4 | 5 | 查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( 9 | `emp_no` int(11) NOT NULL, 10 | `dept_no` char(4) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `employees` ( 15 | `emp_no` int(11) NOT NULL, 16 | `birth_date` date NOT NULL, 17 | `first_name` varchar(14) NOT NULL, 18 | `last_name` varchar(16) NOT NULL, 19 | `gender` char(1) NOT NULL, 20 | `hire_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`)); 22 | ``` 23 | 24 | ## 题解 25 | 26 | ```mysql 27 | select last_name,first_name,dept_no from employees e left join dept_emp d on e.emp_no=d.emp_no 28 | ``` 29 | 30 | ## 题解 31 | 32 | left join的用法 33 | 34 | -------------------------------------------------------------------------------- /50.将employees表中的所有员工的last_name和first_name通过连接起来.md: -------------------------------------------------------------------------------- 1 | # 将employees表中的所有员工的last_name和first_name通过(')连接起来 2 | 3 | ## 题目描述 4 | 5 | 将employees表中的所有员工的last_name和first_name通过(')连接起来。 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select last_name || "'" || first_name name from employees 22 | ``` 23 | 24 | ## 题解 25 | 26 | 牛客网OJ使用sqlite,无法使用concat进行字段拼接。MySQL格式: 27 | 28 | ```mysql 29 | select concat(last_name,'\'',first_name) name from employees 30 | ``` 31 | 32 | -------------------------------------------------------------------------------- /51.查找字符串.md: -------------------------------------------------------------------------------- 1 | # 查找字符串'10,A,B' 中逗号','出现的次数cnt 2 | 3 | ## 题目描述 4 | 5 | 查找字符串'10,A,B' 中逗号','出现的次数cnt。 6 | 7 | ## 答案 8 | 9 | ```mysql 10 | select length('10,A,B') - length(replace('10,A,B',',','')) cnt 11 | ``` 12 | 13 | ## 题解 14 | 15 | 利用字符串替换函数,将子串替换为空。(源串长度-替换后的串长度)/子串长度=子串出现次数 -------------------------------------------------------------------------------- /52.获取Employees中的first_name.md: -------------------------------------------------------------------------------- 1 | # 获取Employees中的first_name 2 | 3 | ## 题目描述 4 | 5 | 获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select first_name from employees order by substr(first_name,-2) asc 22 | ``` 23 | 24 | ## 题解 25 | 26 | 字符串函数substr的使用 -------------------------------------------------------------------------------- /53.按照dept_no进行汇总.md: -------------------------------------------------------------------------------- 1 | # 按照dept_no进行汇总 2 | 3 | ## 题目描述 4 | 5 | 按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( 9 | `emp_no` int(11) NOT NULL, 10 | `dept_no` char(4) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select dept_no,group_concat(emp_no) from dept_emp group by dept_no 20 | ``` 21 | 22 | ## 题解 23 | 24 | 聚合函数group_concat的使用 -------------------------------------------------------------------------------- /54.查找排除当前最大最小salary之后的员工的平均工资avg_salary.md: -------------------------------------------------------------------------------- 1 | # 查找排除当前最大、最小salary之后的员工的平均工资avg_salary 2 | 3 | ## 题目描述 4 | 5 | 查找排除当前最大、最小salary之后的员工的平均工资avg_salary。 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL, 9 | `salary` int(11) NOT NULL, 10 | `from_date` date NOT NULL, 11 | `to_date` date NOT NULL, 12 | PRIMARY KEY (`emp_no`,`from_date`)); 13 | ``` 14 | 15 | ## 答案 16 | 17 | ```mysql 18 | select avg(salary) avg_salary from salaries s where to_date = '9999-01-01' and salary not in (select min(salary) from salaries where s.to_date = '9999-01-01') and salary not in (select max(salary) from salaries where s.to_date = '9999-01-01') 19 | ``` 20 | 21 | ## 题解 22 | 23 | 使用min和max函数获得最大值最小值,而后用not in将最大值最小值记录去除,求平均 24 | 25 | 1、获得salary最大值maxRecord最小值minRecord记录(逻辑上需要按照当前时间的salary进行筛选) 26 | 27 | ```mysql 28 | select max(salary) from salaries where s.to_date = '9999-01-01') 29 | select min(salary) from salaries where s.to_date = '9999-01-01') 30 | ``` 31 | 32 | 2、去除最大值最小值记录 t1 33 | 34 | ```mysql 35 | select * from salaries where to_data = '9999-01-01' and salary not in maxRecord and salary not in minRecord 36 | ``` 37 | 38 | 3、对上面的临时表求平均值即可 39 | 40 | ```mysql 41 | select avg(salary) from t1 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /55.分页查询employees表.md: -------------------------------------------------------------------------------- 1 | # 分页查询employees表,每5行一页,返回第2页的数据 2 | 3 | ## 题目描述 4 | 5 | 分页查询employees表,每5行一页,返回第2页的数据 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select * from employees limit 5,5; 22 | ``` 23 | 24 | ## 题解 25 | 26 | limit关键字的使用 27 | 28 | limit a,b 29 | 30 | a:从第a条开始,默认0开始 31 | 32 | b:返回b条 -------------------------------------------------------------------------------- /56.获取所有员工的emp_no.md: -------------------------------------------------------------------------------- 1 | # 获取所有员工的emp_no 2 | 3 | ## 题目描述 4 | 5 | 获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和recevied,没有分配具体的员工不显示 6 | 7 | ```mysql 8 | CREATE TABLE `dept_emp` ( `emp_no` int(11) NOT NULL, 9 | `dept_no` char(4) NOT NULL, 10 | `from_date` date NOT NULL, 11 | `to_date` date NOT NULL, 12 | PRIMARY KEY (`emp_no`,`dept_no`)); 13 | CREATE TABLE `dept_manager` ( 14 | `dept_no` char(4) NOT NULL, 15 | `emp_no` int(11) NOT NULL, 16 | `from_date` date NOT NULL, 17 | `to_date` date NOT NULL, 18 | PRIMARY KEY (`emp_no`,`dept_no`)); 19 | CREATE TABLE `employees` ( 20 | `emp_no` int(11) NOT NULL, 21 | `birth_date` date NOT NULL, 22 | `first_name` varchar(14) NOT NULL, 23 | `last_name` varchar(16) NOT NULL, 24 | `gender` char(1) NOT NULL, 25 | `hire_date` date NOT NULL, 26 | PRIMARY KEY (`emp_no`)); 27 | CREATE TABLE `salaries` ( 28 | `emp_no` int(11) NOT NULL, 29 | `salary` int(11) NOT NULL, 30 | `from_date` date NOT NULL, 31 | `to_date` date NOT NULL, 32 | PRIMARY KEY (`emp_no`,`from_date`)); 33 | -- 官网题目缺失表 34 | CREATE TABLE `emp_bonus` ( 35 | `emp_no` int not null, 36 | `recevied` datetime not null, 37 | `btype` smallint not null); 38 | ``` 39 | 40 | ## 答案 41 | 42 | ```mysql 43 | select t1.emp_no, dept_no, btype, recevied from (select e.emp_no,dept_no from employees e,dept_emp de where e.emp_no = de.emp_no) t1 left join emp_bonus eb on t1.emp_no = eb.emp_no 44 | ``` 45 | 46 | ## 题解 47 | 48 | 题目出的稀巴烂!可以挑出各种错误。 49 | 50 | 1、获得所有员工对应的emp_no和dept_no 51 | 52 | ```mysql 53 | select e.emp_no,dept_no from employees e,dept_manager dm where e.emp_no = dm.emp_no 54 | ``` 55 | 56 | 2、要求btype和recevied字段没有分配具体的员工,这两个字段不显示,明示join操作 -------------------------------------------------------------------------------- /57.使用含有关键字exists查找未分配具体部门的员工的所有信息.md: -------------------------------------------------------------------------------- 1 | # 使用含有关键字exists查找未分配具体部门的员工的所有信息 2 | 3 | ## 题目描述 4 | 5 | 使用含有关键字exists查找未分配具体部门的员工的所有信息。 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | CREATE TABLE `dept_emp` ( 17 | `emp_no` int(11) NOT NULL, 18 | `dept_no` char(4) NOT NULL, 19 | `from_date` date NOT NULL, 20 | `to_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`,`dept_no`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select * from employees e1 where not exists (select * from dept_emp de where e1.emp_no = de.emp_no) 28 | ``` 29 | 30 | ## 题解 31 | 32 | 子查询 -------------------------------------------------------------------------------- /58.获取employees中的行数据且这些行也存在于emp_v中.md: -------------------------------------------------------------------------------- 1 | # 获取employees中的行数据,且这些行也存在于emp_v中 2 | 3 | ## 题目描述 4 | 5 | 存在如下的视图,获取employees中的行数据,且这些行也存在于emp_v中。注意不能使用intersect关键字。 6 | 7 | ```mysql 8 | create view emp_v as select * from employees where emp_no >10005; 9 | CREATE TABLE `employees` ( 10 | `emp_no` int(11) NOT NULL, 11 | `birth_date` date NOT NULL, 12 | `first_name` varchar(14) NOT NULL, 13 | `last_name` varchar(16) NOT NULL, 14 | `gender` char(1) NOT NULL, 15 | `hire_date` date NOT NULL, 16 | PRIMARY KEY (`emp_no`)); 17 | ``` 18 | 19 | ## 答案 20 | 21 | ```mysql 22 | select * from emp_v 23 | ``` 24 | 25 | ## 题解 26 | 27 | 出题不严谨,题本意应当是筛选出employees表中,存在于emp_v视图中的相同行。 28 | 29 | 1、可以投机取巧,由于emp_v视图全部来源于employees,所以直接` 30 | 31 | ```mysql 32 | select * from emp_v 33 | ``` 34 | 35 | 2、按照题目原义 36 | 37 | ```mysql 38 | select e.* from employees e,emp_v ev where e.emp_no = ev.emp_no 39 | ``` 40 | 41 | -------------------------------------------------------------------------------- /59.获取有奖金的员工相关信息.md: -------------------------------------------------------------------------------- 1 | # 获取有奖金的员工相关信息 2 | 3 | ## 题目描述 4 | 5 | 获取有奖金的员工相关信息。 6 | 7 | 给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。 bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。 当前薪水表示to_date='9999-01-01' 8 | 9 | ```mysql 10 | CREATE TABLE `employees` ( 11 | `emp_no` int(11) NOT NULL, 12 | `birth_date` date NOT NULL, 13 | `first_name` varchar(14) NOT NULL, 14 | `last_name` varchar(16) NOT NULL, 15 | `gender` char(1) NOT NULL, 16 | `hire_date` date NOT NULL, 17 | PRIMARY KEY (`emp_no`)); 18 | CREATE TABLE `dept_emp` ( 19 | `emp_no` int(11) NOT NULL, 20 | `dept_no` char(4) NOT NULL, 21 | `from_date` date NOT NULL, 22 | `to_date` date NOT NULL, 23 | PRIMARY KEY (`emp_no`,`dept_no`)); 24 | create table emp_bonus( 25 | emp_no int not null, 26 | recevied datetime not null, 27 | btype smallint not null); 28 | CREATE TABLE `salaries` ( 29 | `emp_no` int(11) NOT NULL, 30 | `salary` int(11) NOT NULL, 31 | `from_date` date NOT NULL, 32 | `to_date` date NOT NULL, PRIMARY KEY (`emp_no`,`from_date`)); 33 | ``` 34 | 35 | ## 答案 36 | 37 | ```mysql 38 | -- 一般答案 39 | select eb.emp_no,e.first_name,e.last_name,eb.btype,s.salary,(s.salary*btype*0.1) bonus from emp_bonus eb,employees e,salaries s where eb.emp_no = e.emp_no and eb.emp_no = s.emp_no and s.to_date = '9999-01-01' 40 | 41 | -- 利用条件判断解法 42 | select eb.emp_no, 43 | e.first_name, 44 | e.last_name, 45 | eb.btype, 46 | s.salary, 47 | (case btype 48 | when 1 then s.salary*0.1 49 | when 2 then s.salary*0.2 50 | when 3 then s.salary*0.3 51 | end 52 | ) bonus 53 | from emp_bonus eb, 54 | employees e, 55 | salaries s 56 | where eb.emp_no = e.emp_no 57 | and eb.emp_no = s.emp_no 58 | and s.to_date = '9999-01-01' 59 | ``` 60 | 61 | ## 题解 62 | 63 | 简单的拼表筛选可以解决问题。但是考点是case-when语句 64 | 65 | 语法规则: 66 | 67 | ```mysql 68 | case colume 69 | when condition then result 70 | when condition then result 71 | when condition then result 72 | else result 73 | end 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /6.查找所有员工入职时候的薪水情况.md: -------------------------------------------------------------------------------- 1 | # 查找所有员工入职时候的薪水情况 2 | 3 | ## 题目描述 4 | 5 | 查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | CREATE TABLE `salaries` ( 17 | `emp_no` int(11) NOT NULL, 18 | `salary` int(11) NOT NULL, 19 | `from_date` date NOT NULL, 20 | `to_date` date NOT NULL, 21 | PRIMARY KEY (`emp_no`,`from_date`)); 22 | ``` 23 | 24 | ## 答案 25 | 26 | ```mysql 27 | select e.emp_no,s.salary from employees e left join salaries s on e.emp_no = s.emp_no where e.hire_date = s.from_date order by e.emp_no desc 28 | ``` 29 | 30 | ## 题解 31 | 32 | 两表的简单连接,而后对数据进行排序 -------------------------------------------------------------------------------- /60.统计salary的累计和running_total.md: -------------------------------------------------------------------------------- 1 | # 统计salary的累计和running_total 2 | 3 | ## 题目描述 4 | 5 | 按照salary的累计和running_total,其中running_total为前两个员工的salary累计和,其他以此类推。 具体结果如下Demo展示。 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select s2.emp_no,s2.salary,sum(s1.salary) running_total from (select emp_no,salary from salaries where to_date = '9999-01-01') s1 inner join (select emp_no,salary from salaries where to_date = '9999-01-01') s2 on s1.emp_no <= s2.emp_no group by s2.emp_no 20 | ``` 21 | 22 | ## 题解 23 | 24 | 1、获得当前员工的工资情况s1 25 | 26 | ```mysql 27 | select emp_no,salary from salaries where to_date = '9999-01-01' 28 | ``` 29 | 30 | 2、连接当前员工信息s2,筛选出emp_no小于当前用户的所有员工信息 31 | 32 | ```mysql 33 | s1 inner join (select emp_no,salary from salaries where to_date = '9999-01-01') s2 on s1.emp_no <= s2.emp_no 34 | ``` 35 | 36 | 3、根据emp_no进行分组,对salary列进行求和 37 | 38 | ```mysql 39 | select s2.emp_no,s2.salary,sum(s1.salary) running_total from s1 inner join s2 on s1.emp_no <= s2.emp_no group by s2.emp_no 40 | ``` -------------------------------------------------------------------------------- /61.对于employees表中给出奇数行的first_name.md: -------------------------------------------------------------------------------- 1 | # 对于employees表中,给出奇数行的first_name 2 | 3 | ## 题目描述 4 | 5 | 对于employees表中,给出奇数行的first_name 6 | 7 | ```mysql 8 | CREATE TABLE `employees` ( 9 | `emp_no` int(11) NOT NULL, 10 | `birth_date` date NOT NULL, 11 | `first_name` varchar(14) NOT NULL, 12 | `last_name` varchar(16) NOT NULL, 13 | `gender` char(1) NOT NULL, 14 | `hire_date` date NOT NULL, 15 | PRIMARY KEY (`emp_no`)); 16 | ``` 17 | 18 | ## 答案 19 | 20 | ```mysql 21 | select e1.first_name from employees e1 where (select count(*) from employees e2 where e1.first_name <= e2.first_name) % 2 = 1 22 | ``` 23 | 24 | ## 题解 25 | 26 | 对于MySQL版本来说,可以添加一列临时数据来进行奇偶排序,而后筛选出奇数行 27 | 28 | ```mysql 29 | select first_name from (select (@i := @i +1) sn,employees.* from employees,(select @i := 0) a) t where sn % 2 = 1 30 | ``` 31 | 32 | 先排号码,而后取奇数 33 | 34 | ```mysql 35 | -- 外层获取奇数行 36 | select e1.first_name from employees e1 where (条件) % 2 = 1 37 | ``` 38 | 39 | ```mysql 40 | -- count获得排序号码 41 | select count(*) from employees e2 where e1.first_name <= e2.first_name 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /7.查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t.md: -------------------------------------------------------------------------------- 1 | # 查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t 2 | 3 | ## 题目描述 4 | 5 | 查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select emp_no,count(emp_no) t from salaries group by emp_no having count(emp_no) > 15 20 | ``` 21 | 22 | ## 题解 23 | 24 | 分组后过滤 -------------------------------------------------------------------------------- /8.找出所有员工当前薪水salary情况.md: -------------------------------------------------------------------------------- 1 | # 找出所有员工当前薪水salary情况 2 | 3 | ## 题目描述 4 | 5 | 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示 6 | 7 | ```mysql 8 | CREATE TABLE `salaries` ( 9 | `emp_no` int(11) NOT NULL, 10 | `salary` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`from_date`)); 14 | ``` 15 | 16 | ## 答案 17 | 18 | ```mysql 19 | select distinct salary from salaries where to_date = '9999-01-01' order by salary desc 20 | ``` 21 | 22 | ## 题解 23 | 24 | distinct的作用 -------------------------------------------------------------------------------- /9.获取所有部门当前manager的当前薪水情况.md: -------------------------------------------------------------------------------- 1 | # 获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01' 2 | 3 | ## 题目描述 4 | 5 | 获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01' 6 | 7 | ```mysql 8 | CREATE TABLE `dept_manager` ( 9 | `dept_no` char(4) NOT NULL, 10 | `emp_no` int(11) NOT NULL, 11 | `from_date` date NOT NULL, 12 | `to_date` date NOT NULL, 13 | PRIMARY KEY (`emp_no`,`dept_no`)); 14 | CREATE TABLE `salaries` ( 15 | `emp_no` int(11) NOT NULL, 16 | `salary` int(11) NOT NULL, 17 | `from_date` date NOT NULL, 18 | `to_date` date NOT NULL, 19 | PRIMARY KEY (`emp_no`,`from_date`)); 20 | ``` 21 | 22 | ## 答案 23 | 24 | ```mysql 25 | select dm.dept_no,dm.emp_no,s.salary from dept_manager dm left join salaries s on dm.emp_no = s.emp_no where s.to_date = '9999-01-01' and dm.to_date = '9999-01-01' 26 | ``` 27 | 28 | ## 题解 29 | 30 | 连接后过滤 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 xuthus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 数据库SQL实战 2 | 3 | |选项|说明| 4 | |:--:|:--:| 5 | |:monkey_face:|通过| 6 | |:see_no_evil:|未通过或不符合MySQL5.7语法规范| 7 | 8 | 9 | 10 | | 编号 | 分类 | 标题 | 提交 | 11 | | :--: | :--: | :--------------: | :---: | 12 | | 1 | 过滤 | [查找最晚入职员工的所有信息](1.查找最晚入职员工的所有信息.md) | :monkey_face: | 13 | | 2 | 过滤 | [查找入职员工时间排名倒数第三的员工所有信息](2.查找入职员工时间排名倒数第三的员工所有信息.md) | :monkey_face: | 14 | | 3 | 连接 | [查找当前薪水详情以及部门编号dept_no](3.查找当前薪水详情以及部门编号dept_no.md) | :monkey_face: | 15 | | 4 | 连接 | [查找所有已经分配部门的员工的last_name和first_name](4.查找所有已经分配部门的员工的last_name和first_name.md) | :monkey_face: | 16 | | 5 | 连接 | [查找所有员工的last_name和first_name以及对应部门编号dept_no](5.查找所有员工的last_name和first_name以及对应部门编号dept_no.md) | :monkey_face: | 17 | | 6 | 连接 | [查找所有员工入职时候的薪水情况](6.查找所有员工入职时候的薪水情况.md) | :monkey_face: | 18 | | 7 | 分组 | [查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t](7.查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t.md) | :monkey_face: | 19 | | 8 | 过滤 | [找出所有员工当前薪水salary情况](8.找出所有员工当前薪水salary情况.md) | :monkey_face: | 20 | | 9 | 连接 | [获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date=9999-01-01](9.获取所有部门当前manager的当前薪水情况.md) | :monkey_face: | 21 | | 10 | 过滤 | [获取所有非manager的员工emp_no](10.获取所有非manager的员工emp_no.md) | :monkey_face: | 22 | | 11 | 连接 | [获取所有员工当前的manager](11.获取所有员工当前的manager.md) | :monkey_face: | 23 | | 12 | 分组聚合 | [获取所有部门中当前员工薪水最高的相关信息](12.获取所有部门中当前员工薪水最高的相关信息.md) | :see_no_evil: | 24 | | 13 | 分组聚合 | [从titles表获取按照title进行分组](13.从titles表获取按照title进行分组.md) | :monkey_face: | 25 | | 14 | 分组聚合 | [从titles表获取按照title进行分组](14.从titles表获取按照title进行分组2.md) | :monkey_face: | 26 | | 15 | 过滤 | [查找employees表](15.查找employees表.md) | :monkey_face: | 27 | | 16 | 分组聚合 | [统计出当前各个title类型对应的员工当前薪水对应的平均工资](16.统计出当前各个title类型对应的员工当前薪水对应的平均工资.md) | :monkey_face: | 28 | | 17 | 过滤 | [获取当前薪水第二多的员工的emp_no以及其对应的薪水salary](17.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary.md) | :monkey_face: | 29 | | 18 | 连接 | [获取当前薪水第二多的员工的emp_no以及其对应的薪水salary,不准使用order by](18.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary2.md) | :monkey_face: | 30 | | 19 | 连接 | [查找所有员工的last_name和first_name以及对应的dept_name](19.查找所有员工的last_name和first_name以及对应的dept_name.md) | :monkey_face: | 31 | | 20 | 过滤 | [查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth](20.查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth.md) | :monkey_face: | 32 | | 21 | 连接 | [查找所有员工自入职以来的薪水涨幅情况](21.查找所有员工自入职以来的薪水涨幅情况.md) | :monkey_face: | 33 | | 22 | 分组聚合 | [统计各个部门对应员工涨幅的次数总和](22.统计各个部门对应员工涨幅的次数总和.md) | :monkey_face: | 34 | | 23 | 排名 | [对所有员工的薪水按照salary进行按照1-N的排名](23.对所有员工的薪水按照salary进行按照1-N的排名.md) | :see_no_evil: | 35 | | 24 | 连接 | [获取所有非manager员工当前的薪水情况](24.获取所有非manager员工当前的薪水情况.md) | :monkey_face: | 36 | | 25 | 连接 | [获取员工其当前的薪水比其manager当前薪水还高的相关信息](25.获取员工其当前的薪水比其manager当前薪水还高的相关信息.md) | :monkey_face: | 37 | | 26 | 连接和分组 | [汇总各个部门当前员工的title类型的分配数目](26.汇总各个部门当前员工的title类型的分配数目.md) | :monkey_face: | 38 | | 27 | 连接 | [给出每个员工每年薪水涨幅超过5000的员工编号emp_no](27.给出每个员工每年薪水涨幅超过5000的员工编号emp_no.md) | :see_no_evil: | 39 | | 28 | 连接 | [查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部](28.查找描述信息中包括robot的电影对应的分类名称以及电影数目.md) | :monkey_face: | 40 | | 29 | 连接 | [使用join查询方式找出没有分类的电影id以及名称](29.使用join查询方式找出没有分类的电影id以及名称.md) | :monkey_face: | 41 | | 30 | 子查询 | [使用子查询的方式找出属于Action分类的所有电影对应的title,description](30.使用子查询.md) | :monkey_face: | 42 | | 31 | 优化 | [获取 select * from employees 对应的执行计划](31.获取select对应的执行计划.md) | :monkey_face: | 43 | | 32 | 字符串处理 | [将employees表的所有员工的last_name和first_name拼接起来作为Name](32.将employees表的所有员工的last_name和first_name拼接起来作为Name.md) | :see_no_evil: | 44 | | 33 | 表操作 | [创建一个actor表,包含如下列信息](33.创建一个actor表.md) | :see_no_evil: | 45 | | 34 | 数据操作 | [批量插入数据](34.批量插入数据.md) | :monkey_face: | 46 | | 35 | 数据操作 | [批量插入数据,不使用replace操作](35.批量插入数据不使用replace操作.md) | :see_no_evil: | 47 | | 36 | 表和数据操作 | [创建一个actor_name表](36.创建一个actor_name表.md) | :monkey_face: | 48 | | 37 | 索引 | [对first_name创建唯一索引uniq_idx_firstname](37.对first_name创建唯一索引uniq_idx_firstname.md) | :monkey_face: | 49 | | 38 | 视图 | [针对actor表创建视图actor_name_view](38.针对actor表创建视图actor_name_view.md) | :monkey_face: | 50 | | 39 | 索引 | [针对上面的salaries表emp_no字段创建索引idx_emp_no](39.针对上面的salaries表emp_no字段创建索引idx_emp_no.md) | :see_no_evil: | 51 | | 40 | 表操作 | [在last_update后面新增加一列名字为create_date](40.在last_update后面新增加一列名字为create_date.md) | :see_no_evil: | 52 | | 41 | 触发器 | [构造一个触发器audit_log](41.构造一个触发器audit_log.md) | :monkey_face: | 53 | | 42 | 数据操作 | [删除emp_no重复的记录,只保留最小的id对应的记录](42.删除emp_no重复的记录只保留最小的id对应的记录.md) | :monkey_face: | 54 | | 43 | 数据操作 | [将所有to_date为9999-01-01的全部更新为NULL](43.将所有to_date为9999-01-01的全部更新为NULL.md) | :monkey_face: | 55 | | 44 | 数据操作 | [将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005](44.将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005.md) | :monkey_face: | 56 | | 45 | 表操作 | [将titles_test表名修改为titles_2017](45.将titles_test表名修改为titles_2017.md) | :monkey_face: | 57 | | 46 | 外键 | [在audit表上创建外键约束,其emp_no对应employees_test表的主键id](46.在audit表上创建外键约束其emp_no对应employees_test表的主键id.md) | :monkey_face: | 58 | | 47 | 连接 | [如何获取emp_v和employees有相同的数据no](47.如何获取emp_v和employees有相同的数据no.md) | :monkey_face: | 59 | | 48 | 数据操作 | [将所有获取奖金的员工当前的薪水增加10%](48.将所有获取奖金的员工当前的薪水增加10%.md) | :monkey_face: | 60 | | 49 | 字符串处理 | [针对库中的所有表生成select count(*)对应的SQL语句](49.针对库中的所有表生成对应的SQL语句.md) | :see_no_evil: | 61 | | 50 | 字符串处理 | [将employees表中的所有员工的last_name和first_name通过(')连接起来](50.将employees表中的所有员工的last_name和first_name通过连接起来.md) | :see_no_evil: | 62 | | 51 | 字符串处理 | [查找字符串'10,A,B' 中逗号','出现的次数cnt](51.查找字符串.md) | :monkey_face: | 63 | | 52 | 字符串处理 | [获取Employees中的first_name](52.获取Employees中的first_name.md) | :monkey_face: | 64 | | 53 | 聚合函数 | [按照dept_no进行汇总](53.按照dept_no进行汇总.md) | :monkey_face: | 65 | | 54 | 聚合函数 | [查找排除当前最大、最小salary之后的员工的平均工资avg_salary](54.查找排除当前最大最小salary之后的员工的平均工资avg_salary.md) | :monkey_face: | 66 | | 55 | 关键字 | [分页查询employees表,每5行一页,返回第2页的数据](55.分页查询employees表.md) | :monkey_face: | 67 | | 56 | 连接 | [获取所有员工的emp_no](56.获取所有员工的emp_no.md) | :monkey_face: | 68 | | 57 | 子查询 | [使用含有关键字exists查找未分配具体部门的员工的所有信息](57.使用含有关键字exists查找未分配具体部门的员工的所有信息.md) | :monkey_face: | 69 | | 58 | 视图 | [获取employees中的行数据,且这些行也存在于emp_v中](58.获取employees中的行数据且这些行也存在于emp_v中.md) | :monkey_face: | 70 | | 59 | 条件语句 | [获取有奖金的员工相关信息](59.获取有奖金的员工相关信息.md) | :monkey_face: | 71 | | 60 | 表的复用 | [统计salary的累计和running_total](60.统计salary的累计和running_total.md) | :monkey_face: | 72 | | 61 | 表的复用 | [对于employees表中,给出奇数行的first_name](61.对于employees表中给出奇数行的first_name.md) | :see_no_evil: | 73 | 74 | **答案全部在牛客网测试通过。语法规格SQLite3.7.9** 75 | 76 | 题解主要有参考[牛课网论坛](https://www.nowcoder.com/ta/sql) 77 | 78 | 本地测试使用**MySQL5.7**,部分语法与**SQLite**存在差异,对于MySQL5.7+,请设置**sql_mode**,正确使用group by(解决**ONLY_FULL_GROUP_BY**导致的group by查询条件严苛问题,此方法只做临时修改) 79 | 80 | ```mysql 81 | set sql_mode=(select replace(@@sql_mode,'ONLY_FULL_GROUP_BY','')); 82 | ``` 83 | 84 | 详情参考:[MySQL的sql_mode解析与设置](https://www.cnblogs.com/fireporsche/p/8618691.html) 85 | 86 | ## 离线练习数据集配置 87 | 88 | > 牛客网的数据结构几乎与MySQL测试用的数据集相通,可以先在本地测试后,再在牛客网提交结果 89 | 90 | 1. 前往 https://launchpad.net/test-db/employees-db-1/1.0.6 下载文件 **employees_db-full-1.0.6.tar.bz2** 91 | 92 | 2. 解压缩下载的文件 93 | 94 | ```bash 95 | tar jxvf employees_db-full-1.0.6.tar.bz2 96 | cd employees_db-full-1.0.6 97 | ``` 98 | 99 | 3. 修改文件 employees.sql 100 | 101 | ```bash 102 | # 38行 set storage_engine = InnoDB; 替换 103 | set default_storage_engine = InnoDB; 104 | # 44行 select CONCAT('storage engine: ', @@storage_engine) as INFO; 替换 105 | select CONCAT('storage engine: ', @@default_storage_engine) as INFO; 106 | ``` 107 | 108 | 4. 导入数据库 109 | 110 | ```bash 111 | mysql -uroot -p -t < employees.sql 112 | ``` 113 | 114 | 参考:https://blog.csdn.net/appleyuchi/article/details/79439387 115 | 116 | GitHub:https://github.com/datacharmer/test_db 117 | --------------------------------------------------------------------------------