在牛客网刷数据库的题目 https://www.nowcoder.com/ta/sql
1.查找最晚入职员工的所有信息(select)
select * from employees order by hire_date desc
limit 1;
//最关键在于limit 1 ,表示总共只选择一个;(两个参数表示分页)
//desc降序
2.查找入职员工时间排名倒数第三的员工所有信息(select)
select * from employees order by hire_date desc limit 1 offset 2
//关键点在于offset
//limit 1 offset 2 ==>表示第3个
select s.emp_no,salary,from_date,s.to_date,dept_no from salaries as s join dept_manager as d where s.emp_no=d.emp_no and s.to_date='9999-01-01' and d.to_date='9999-01-01' //表示"当前"(本题特色) order by s.emp_no
4.查找所有已经分配部门的员工的last_name和first_name以及dept_no(select)
select last_name,first_name,dept_no from dept_emp as d left join employees as e on d.emp_no=e.emp_no
//这里用left join或者inner join(join)都一样可以
//第一行里面,如果字段不是多表共有的,就可以不用指出是哪个表的属性(例e.last_name)
5.查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括暂时没有分配部门的员工(请注意输出描述里各个列的前后顺序)
select last_name,first_name,dept_no from dept_emp as d right join employees as e on d.emp_no=e.emp_no //重点是:right join
6.查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序(select)
select e.emp_no,salary from employees as e left join salaries as s on e.emp_no=s.emp_no and e.hire_date=s.from_date order by e.emp_no desc
//join后面紧接着on,并说明两表join的字段
//善用缩进,可以使结构清晰
7.查找薪水变动超过15次的员工号emp_no以及其对应的变动次数t (select,较难)
select emp_no,t from( select emp_no, count(salary) as t from salaries group by emp_no )alias_name where t>15
//这个是典型的两次select查询,第一次select形成一张新的表(包括新的字段:count)用于给第二个select来查询
//select...from(...)alias_name where... 这是外层select,将alias_name表作为查询对象
//内层select先分组,再查询count信息
8.找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示
select distinct(salary) from salaries where to_date='9999-01-01' order by salary desc //select后面直接跟distinct()来去重
9.获取所有部门当前(dept_manager.to_date='9999-01-01')manager的当前(salaries.to_date='9999-01-01')薪水情况,给出dept_no, emp_no以及salary,输出结果按照dept_no升序排列(请注意,同一个人可能有多条薪水情况记录)
select dept_no,d.emp_no,salary from dept_manager as d join salaries as s on d.emp_no=s.emp_no where d.to_date='9999-01-01' and s.to_date='9999-01-01' order by dept_no
10.获取所有非manager的员工emp_no
select e.emp_no from employees as e where e.emp_no not in ( select d.emp_no from dept_manager as d )
11.获取所有员工当前的(dept_manager.to_date='9999-01-01')manager,如果员工是manager的话不显示(也就是如果当前的manager是自己的话结果不显示)。输出结果第一列给出当前员工的emp_no,第二列给出其manager对应的emp_no。
select e.emp_no, m.emp_no as manager_no from dept_emp as e join dept_manager as m on e.dept_no = m.dept_no where e.emp_no!=m.emp_no and m.to_date='9999-01-01' //这两个比较重要: //where e.emp_no!=m.emp_no //m.emp_no as manager_no
33.创建一个actor表(create table)
create table actor( actor_id smallint(5) not null primary key, first_name varchar(45) not null, last_name varchar(45) not null, last_update date not null )
//主键直接在字段最后加上primary key就行
34.请你对于表actor批量插入如下数据(insert)
insert into actor values (1,'PENELOPE','GUINESS','2006-02-15 12:34:33'), (2,'NICK','WAHLBERG','2006-02-15 12:34:33')
//varchar、date、time都要用单引号包起来(红字)
//第一行也可以写成insert into actor(actor_id,first_name,last_name,last_update),但是如果全部&有序,就可以省略表项字段
42.删除emp_no重复的记录,只保留最小的id对应的记录(delete,较难)
delete from titles_test where id not in( select * from( select min(id)
from titles_test group by emp_no )alias_name )
//delete from...where...固定套路
//not in 表示不在某范围
//select * from(...)alias_name 是嵌套一层别名(mysql-8.0不允许查找的同时删除,需要起别名)
//select的执行次序,在group by、having之后,所以可以先分组再从每个组里面分别select值
48.请你写出更新语句,将所有获取奖金的员工当前的(salaries.to_date='9999-01-01')薪水增加10%。(emp_bonus里面的emp_no都是当前获奖的所有员工)
(update)
方法1:连接查询(先join两张表)
update salaries as s join emp_bonus as e on s.emp_no=e.emp_no set salary=salary*1.1 where to_date='9999-01-01'
//update...set...where... ==>固定套路
//set后面跟表达式
方法2:子查询(两次select)
update salaries set salary=salary*1.1 where to_date='9999-01-01' and salaries.emp_no in(select emp_no from emp_bonus)
//这个in很关键,要区别于 "="
比较:
推荐使用连接查询(JOIN)
连接查询不需要创建+销毁临时表,因此速度比子查询快。