之前的综合题有点难度。
这部分是牛客上面的题目,自我总结:
- 简单的一次条件限制的可以轻松写出来;
- 需要进行嵌套的子查询,逻辑不清;
- 有些函数不太知道。
https://www.nowcoder.com/ta/sql
1.查找最晚入职员工的所有信息
使用子查询
# 日期相同也无碍 SELECT * FROM employees WHERE hire_date = (SELECT max(hire_date) FROM employees)
# 只能输出一条 SELECT * FROM employees ORDER BY hire_date DESC LIMIT 1;
2.查找入职员工时间排名倒数第三的员工所有信息
先完成子查询,然后根据找到的时间排名,确定该员工所有的信息
# 若存在同一天多人入职,不好使
SELECT * FROM employees ORDER BY hire_date DESC LIMIT 1 OFFSET 2;
SELECT * FROM employees WHERE hire_date=( SELECT DISTINCT hire_date FROM employees ORDER BY hire_date DESC LIMIT 1 OFFSET 2 );
3.查找当前薪水详情以及部门编号dept_no
只使用where
使用内连接
使用右连接
select salaries.emp_no,salary,from_date,salaries.to_date,dept_no from salaries,dept_manager where salaries.emp_no = dept_manager.emp_no
and dept_manager.to_date='9999-01-01'
and salaries.to_date='9999-01-01' order by salaries.emp_no;
select s.*,d.dept_no from salaries as s inner join dept_manager as d on s.emp_no = d.emp_no where s.to_date = '9999-01-01' and d.to_date = '9999-01-01';
select s.*,d.dept_no from salaries as s right join dept_manager as d on s.emp_no = d.emp_no
4.查找所有已经分配部门的员工的last_name和first_name以及dept_no
右连接
select e.last_name,e.first_name,d.dept_no from employees as e right join dept_emp as d on e.emp_no = d.emp_no;
5.查找所有员工的last_name和first_name以及对应部门编号dept_no
左连接
select e.last_name,e.first_name,d.dept_no from employees as e left join dept_emp as d on e.emp_no = d.emp_no;
7.查找薪水记录超过15次的员工号emp_no以及其对应的记录次数t
count函数,分组group by
HAVING语句在GROUP BY语句之后;SQL会在分组之后计算HAVING语句
select emp_no,count(distinct from_date) as t from salaries group by emp_no having t>15;
8.找出所有员工当前薪水salary情况
select distinct(salary) from salaries order by salary desc;
10.获取所有非manager的员工emp_no
not in
子查询
select emp_no from employees where emp_no not in (select emp_no from dept_manager);
左连接
is null
select e.emp_no from employees as e left join dept_manager as d on e.emp_no=d.emp_no where dept_no is null;
11.获取所有员工当前的manager
select dept_emp.emp_no, dept_manager.emp_no manager from dept_emp ,dept_manager where dept_emp.dept_no = dept_manager.dept_no and dept_emp.emp_no <> dept_manager.emp_no
☆12.获取每个部门中当前员工薪水最高的相关信息(难)
内连接,外表,内表查询每个部门工资最高的
外表与内表,固定部门
select d.dept_no,d.emp_no,s.salary from dept_emp as d inner join salaries as s on d.emp_no = s.emp_no where s.salary in ( select max(s2.salary) from dept_emp as d2 inner join salaries as s2 on d2.emp_no = s2.emp_no and d2.dept_no = d.dept_no #最高薪水,员工表连接 ) order by d.dept_no;
15.查找employees表emp_no与last_name的员工信息
select * from employees where emp_no % 2 = 1 and last_name != 'Mary' order by hire_date desc
select * from employees where MOD(emp_no, 2)=1 and last_name != 'Mary' order by hire_date desc
16.统计出当前各个title类型对应的员工当前薪水对应的平均工资
select title,avg(s.salary) from titles as t join salaries as s on t.emp_no = s.emp_no group by title order by avg(s.salary)
17.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary
子查询
select emp_no,salary from salaries where salary=( select distinct salary from salaries order by salary desc limit 1,1 # 第二名 )
☆18.获取当前薪水第二多的员工的emp_no以及其对应的薪水salary(不能使用order by)
先找出去除第一后的最大值,子查询
去除第一,子查询
select e.emp_no,salary,last_name,first_name from employees as e inner join salaries as s on e.emp_no = s.emp_no where salary=( SELECT max(salary) FROM salaries WHERE to_date='9999-01-01' AND salary<( SELECT MAX(salary) FROM salaries WHERE to_date='9999-01-01' )# 去除最大值后的新最大值 )
19.查找所有员工的last_name和first_name以及对应的dept_name
有人没部门,左连接
部门表与部门员工表,一对一,内连接
SELECT e.last_name, e.first_name, b.dept_name FROM employees AS e LEFT JOIN (SELECT d.dept_no,d.dept_name,de.emp_no FROM departments AS d INNER JOIN dept_emp AS de ON d.dept_no=de.dept_no ) AS b ON e.emp_no=b.emp_no;
21.查找在职员工自入职以来的薪水涨幅情况
select b.emp_no,(b.salary-a.salary) as growth from (select e.emp_no,s.salary from employees as e join salaries as s on e.emp_no = s.emp_no and e.hire_date = s.from_date) as a #入职时候的工资 inner join (select e.emp_no,s.salary from employees as e join salaries as s on e.emp_no = s.emp_no where s.to_date = '9999-01-01')as b#离职时候的工资 on a.emp_no=b.emp_no order by growth
22.统计各个部门的工资记录数
聚合函数group by
连接
行数count
子查询:首先将部门员工关系表与薪水表(有的人不止一条记录)联系起来,每个人属于哪一个部门,几条薪水记录
与部门表联系起来,配对上部门的名字
select de.dept_no,dept_name,t.sum from departments as de left join (select s.emp_no,dept_no,count(d.dept_no) as sum from dept_emp as d join salaries as s on d.emp_no = s.emp_no group by dept_no ) as t on de.dept_no = t.dept_no
☆23.对所有员工的薪水按照salary降序进行1-N的排名
窗口函数dense_rank(),1,1,1,2······
rank(),1,1,1,4······
row_number(),1,2,3,4······
over ( ) as XXX
select emp_no,salary,dense_rank() over (order by salary desc) as paiming from salaries where to_date='9999-01-01' order by paiming asc,emp_no asc
24.获取所有非manager员工当前的薪水情况
select t.dept_no,t.emp_no,f.salary from (select de.emp_no,de.dept_no from dept_emp as de right join dept_manager as dep on de.emp_no != dep.emp_no) as t # 非经理的员工 left join (select e.emp_no,salary,to_date from salaries as s inner join employees as e on e.emp_no = s.emp_no where s.to_date='9999-01-01') as f on t.emp_no = f.emp_no
(up这段有问题,!= 这部分有问题,)
select t.dept_no,t.emp_no,s.salary from (select de.emp_no,de.dept_no from dept_emp as de left join dept_manager as dep on de.emp_no = dep.emp_no where dep.emp_no is null) as t # 非经理的员工 inner join employees e on t.emp_no = e.emp_no #部门员工关系表 inner join salaries s on t.emp_no = s.emp_no #薪水表 where s.to_date='9999-01-01'
select dep.dept_no, t.emp_no, s.salary from( select e.emp_no from employees e left join dept_manager ma on e.emp_no = ma.emp_no where ma.emp_no is null # 非经理人员的emp_no ) t inner join dept_emp dep on t.emp_no = dep.emp_no #部门员工关系表 inner join salaries s on t.emp_no = s.emp_no #薪水表 where s.to_date='9999-01-01'
25.获取员工其当前的薪水比其manager当前薪水还高的相关信息
我的思路:
- 找出员工薪水
- 找出经理薪水
- 通过部门连接员工与经理
- 筛选工资条件
select * from (select de.emp_no emp_no,de.dept_no from dept_emp as de left join dept_manager as dep on de.emp_no = dep.emp_no where dep.emp_no is null) as t1 # 找出员工 left join (select de.emp_no manager_no,de.dept_no from dept_emp as de left join dept_manager as dep on de.emp_no = dep.emp_no where dep.emp_no is not null) as t2 # 找出经理 on t1.dept_no=t2.dept_no
10001|d001|10002|d001
select DISTINCT emp_no,manager_no,emp_salary,manager_salary from (select t1.emp_no,t1.dept_no,salary emp_salary from (select de.emp_no emp_no,de.dept_no from dept_emp as de left join dept_manager as dep on de.emp_no = dep.emp_no where dep.emp_no is null) as t1 # 找出员工 inner join salaries as s on t1.emp_no=s.emp_no) m left join (select t2.manager_no,t2.dept_no,salary manager_salary from (select de.emp_no manager_no,de.dept_no from dept_emp as de left join dept_manager as dep on de.emp_no = dep.emp_no where dep.emp_no is not null) as t2# 找出经理 inner join salaries as s on t2.manager_no=s.emp_no) n on m.dept_no=n.dept_no where manager_salary<emp_salary
https://www.nowcoder.com/practice/f858d74a030e48da8e0f69e21be63bef?tpId=82&tags=&title=&difficulty=0&judgeStatus=0&rp=1
26.汇总各个部门当前员工的title类型的分配数目
- 每个员工所在部门+部门名(部门号)
- 上表和职称表相连(员工号)
- 可以根据两个条件分组,且有优先顺序
select * from dept_emp left join departments on dept_emp.dept_no=departments.dept_no
10001|d001|1986-06-26|9999-01-01|d001|Marketing
10002|d001|1996-08-03|9999-01-01|d001|Marketing
10003|d002|1995-12-03|9999-01-01|d002|Finance
select dept_no,dept_name,title,count(title) count from (select dept_emp.dept_no,emp_no,dept_name from dept_emp left join departments on dept_emp.dept_no=departments.dept_no) as t join titles on t.emp_no=titles.emp_no group by dept_no,title order by dept_no
28.查找描述信息中包含robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部
- 满足条件的电影分类有哪些select film_id,category_id,count(film_id) category_num from film_category GROUP BY category_id having count(film_id)>=5
- 描述中含有robot
- 电影分类名称以及数目
select category.name,count(film.film_id) from
(select film_id,category_id,count(film_id) category_num from film_category GROUP BY category_id having count(film_id)>=5) as t,
film,category,film_category
where film.description LIKE '%robot%'
and film.film_id=film_category.film_id and category.category_id=film_category.category_id # 三个表相连 and t.category_id=category.category_id # 满足条件的电影分类