牛客网:数据库sql实战

时间:2022-09-13 23:49:44

牛客网:数据库sql实战

1、查找最晚入职员工的所有信息

select * from employees where hire_date = (select max(hire_date) from employees);
2、查找入职员工时间排名倒数第三的员工所有

select * from employees where hire_date = (select hire_date from employees order by hire_date desc limit 2, 1);

limit m, n 表示从第m+1条开始,取n条数据

牛客网:数据库sql实战

牛客网:数据库sql实战

3、查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no

select s.*, d.dept_no from salaries s, dept_manager d 
where s.emp_no = d.emp_no and s.to_date = '9999-01-01' and d.to_date = '9999-01-01';
牛客网:数据库sql实战

4、查找所有已经分配部门的员工的last_name和first_name

内连接:
select e.last_name, e.first_name, d.dept_no from employees e inner join dept_emp d on e.emp_no = d.emp_no;
自然连接:
select last_name, first_name, dept_no from dept_emp natural join employees;

 5、查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工

select e.last_name, e.first_name, d.dept_no from employees e left join dept_emp d on d.emp_no = e.emp_no;

6、查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序

select e.emp_no, s.salary from employees e, salaries s
where e.emp_no = s.emp_no and e.hire_date = s.from_date order by e.emp_no desc;

7、查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t

select emp_no, count(*) from salaries group by emp_no having count(*) > 15;

8、找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示

select distinct salary from salaries where to_date = '9999-01-01' order by salary desc;

9、获取所有部门当前manager的当前薪水情况,给出dept_no,emp_no以及salary,当前表示to_date='9999-01-01'

select d.dept_no, d.emp_no, s.salary from salaries s, dept_manager d
where d.emp_no = s.emp_no and d.to_date = '9999-01-01' and s.to_date = '9999-01-01';

10、获取所有非manager的员工emp_no

select e.emp_no from employees e where e.emp_no not in (select emp_no from dept_manager);

11、获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。

select d.emp_no, m.emp_no from dept_emp d, dept_manager m where d.dept_no = m.dept_no and d.emp_no <> m.emp_no and d.to_date = '9999-01-01' and m.to_date = '9999-01-01';

12、获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary

select d.dept_no, s.emp_no, max(s.salary) as salary from dept_emp d, salaries s
where s.emp_no = d.emp_no and d.to_date = '9999-01-01' and s.to_date = '9999-01-01' group by d.dept_no;
牛客网:数据库sql实战

13、从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。

select title, count(*) from titles group by title having count(*) >= 2;

14、从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t,注意对于重复的emp_no进行忽略。

select distinct title, count(distinct emp_no) t from titles group by title having t >= 2;

15、查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列

select * from employees where emp_no%2 = 1 and last_name <> 'Mary' order by hire_date desc;

16、统计出当前各个title类型对应的员工当前薪水对应的平均工资。结果给出title以及平均工资avg。

select t.title, avg(s.salary) from titles t, salaries s
where t.emp_no = s.emp_no and t.to_date = '9999-01-01' and s.to_date = '9999-01-01' group by t.title;

17、获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary

select emp_no, salary from salaries where to_date = '9999-01-01' order by salary desc limit 1,1;

18、查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by

select e.emp_no, max(s.salary) as salary, e.last_name, e.first_name from employees e, salaries s
where e.emp_no = s.emp_no and s.to_date = '9999-01-01' and s.salary != (select max(salary) from salaries where to_date = '9999-01-01');
牛客网:数据库sql实战

19、查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

select e.last_name, e.first_name, dm.dept_name from employees e left join dept_emp d on e.emp_no = d.emp_no left join departments dm on d.dept_no = dm.dept_no;

20、查找员工编号emp_now为10001其自入职以来的薪水salary涨幅值growth

select (select salary from salaries where emp_no = 10001 order by to_date desc limit 1) -
(select salary from salaries where emp_no = 10001 order by to_date limit 1) growth;

21、查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_noy以及其对应的薪水涨幅growth,并按照growth进行升序

select sta.emp_no,(cur.salary-sta.salary) growth from
(select e.emp_no, s.salary from employees e, salaries s where s.emp_no = e.emp_no and s.to_date = '9999-01-01') cur, #查找目前的工资
(select e.emp_no, s.salary from employees e, salaries s where s.from_date = e.hire_date and s.emp_no = e.emp_no) sta #查找入职时候的工资
where cur.emp_no = sta.emp_no order by growth;

22、统计各个部门对应员工涨幅的次数总和,给出部门编码dept_no、部门名称dept_name以及次数sum

select dm.dept_no, dm.dept_name, count(s.salary) sum from
salaries s inner join dept_emp d on s.emp_no = d.emp_no
inner join departments dm on d.dept_no = dm.dept_no
group by d.dept_no;

23、对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照emp_no升序排列

select s1.emp_no, s1.salary, count(distinct s2.salary) rank 
from salaries s1, salaries s2
where s1.to_date = '9999-01-01' and s2.to_date = '9999-01-01'
and s1.salary <= s2.salary
group by s1.emp_no
order by s1.salary desc, s1.emp_no;

24、获取所有非manager员工当前的薪水情况,给出dept_no、emp_no以及salary ,当前表示to_date='9999-01-01'

select d.dept_no, e.emp_no, s.salary
from employees e inner join salaries s on e.emp_no = s.emp_no and s.to_date = '9999-01-01'
inner join dept_emp d on s.emp_no = d.emp_no
where d.emp_no not in (select emp_no from dept_manager);

25、获取员工其当前的薪水比其manager当前薪水还高的相关信息,当前表示to_date='9999-01-01',结果第一列给出员工的emp_no,第二列给出其manager的manager_no,第三列给出该员工当前的薪水emp_salary,第四列给该员工对应的manager当前的薪水manager_salary

select s1.emp_no emp_no, s2.emp_no manager_no, s1.salary emp_salary, s2.salary manager_salary 
from (select d.emp_no, d.dept_no, s.salary from dept_emp d, salaries s
where d.emp_no = s.emp_no and s.to_date = '9999-01-01' and
d.emp_no not in (select emp_no from dept_manager)) s1,
(select dm.emp_no, dm.dept_no, s.salary from dept_manager dm, salaries s
where dm.emp_no = s.emp_no and s.to_date = '9999-01-01') s2
where s1.salary > s2.salary and s1.dept_no=s2.dept_no;

26、汇总各个部门当前员工的title类型的分配数目,结果给出部门编号dept_no、dept_name、其当前员工所有的title以及该类型title对应的数目count

select dm.dept_no, dm.dept_name, t.title, count(t.title) count
from dept_emp d inner join titles t on d.emp_no = t.emp_no and d.to_date = '9999-01-01' and t.to_date = '9999-01-01'
inner join departments dm on d.dept_no = dm.dept_no
group by d.dept_no, t.title;

27、给出每个员工每年薪水涨幅超过5000的员工编号emp_no、薪水变更开始日期from_date以及薪水涨幅值salary_growth,并按照salary_growth逆序排列。

提示:在sqlite中获取datetime时间对应的年份函数为strftime('%Y', to_date)

select s2.emp_no, s1.from_date, (s1.salary - s2.salary) salary_growth
from salaries s2, salaries s1
where s2.emp_no = s1.emp_no
and salary_growth > 5000
and ((strftime("%Y", s1.to_date) -strftime("%Y", s2.to_date)) = 1
or (strftime("%y", s1.from_date) -strftime("%y", s2.from_date)) = 1)
order by salary_growth desc;
牛客网:数据库sql实战

28、查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=2部

select c.name, count(f.film_id) count
from (film f inner join film_category fc on f.film_id = fc.film_id)
inner join category c on c.category_id = fc.category_id
where f.description like '%robot%'
group by c.name
having count>=2;

29、使用join查询方式找出没有分类的电影id以及名称

select f.film_id, f.title from
film f left join film_category fc on f.film_id = fc.film_id
where fc.category_id is null;

30、使用子查询的方式找出属于Action分类的所有电影对应的title,description

select f.title, f.description from
(select fc.film_id from film_category fc, category c
where fc.category_id = c.category_id and c.name = 'Action') a,
film f where f.film_id = a.film_id;

31、获取select * from employees对应的执行计划

explain select * from employees;

32、将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分

select last_name||' '||first_name name from employees;

33、创建一个actor表,包含如下列信息

牛客网:数据库sql实战
create table if not exists actor
(actor_id smallint(5) not null,
first_name varchar(45) not null,
last_name varchar(45) not null,
last_update timestamp not null default (datetime('now','localtime'))
PRIMARY KEY(actor_id));

34、对于表actor批量插入如下数据

insert into actor values(1,'PENELOPE','GUINESS','2006-02-15 12:34:33'),
(2,'NICK','WAHLBERG','2006-02-15 12:34:33');

35、对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作

insert OR ignore into actor values(3,'ED','CHASE','2006-02-15 12:34:33');
#备注:mysql中需要删除or

36、创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。

牛客网:数据库sql实战
create table actor_name(first_name varchar(45) not null,
last_name varchar(45) not null);
insert into actor_name select first_name, last_name from actor;

37、针对表actor中first_name创建唯一索引uniq_idx_firstname,对last_name创建普通索引idx_lastname

CREATE UNIQUE INDEX uniq_idx_firstname ON actor(first_name);
CREATE INDEX idx_lastname ON actor(last_name);

38、针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:

create view actor_name_view as select first_name first_name_v, last_name last_name_v from actor;

39、针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引。

select * from salaries indexed by idx_emp_no where emp_no = 10005;
#在mysql中用force index select * from salaries force index idx_emp_no where emp_no = 10005;

40、针对actor表,现在在last_update后面新增加一列名字为create_date,类型为datetime, NOT NULL,默认值为'0000-00-00 00:00:00'

alter table actor add create_date datetime not null default '0000-00-00 00:00:00';

41、构造一个触发器audit_log,在向employees表中插入一条数据的时候,触发插入相关的数据到audit中。

create trigger audit_log after
insert on employees_test
begin
insert into audit values(new.id,new.name);
end;

42、删除emp_no重复的记录,只保留最小的id对应的记录。

思路:第一步:按emp_no分组,选出每组最小的id;

     第二步:删除数据,id不在上述id内。

delete from titles_test where id not in
(select min(id) from titles_test group by emp_no);

43、将所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。

update titles_test set to_date = null,from_date = '2001-01-01';

44、将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。

update titles_test set emp_no=replace(emp_no,10001,10005) where id=5;

45、将titles_test表名修改为titles_2017。

alter table titles_test rename to titles_2017;

46、在audit表上创建外键约束,其emp_no对应employees_test表的主键id。

ALTER TABLE audit ADD FOREIGN KEY (emp_no) REFERENCES employees_test (id);

47、create view emp_v asselect * from employees where emp_no >10005;
如何获取emp_v和employees有相同的数据?

select e.* from employees e, emp_v ev where e.emp_no = ev.emp_no;
牛客网:数据库sql实战

48、将所有获取奖金的员工当前的薪水增加10%。

update salaries set salary = salary*1.1 where emp_no in
(select s.emp_no from salaries s, emp_bonus e
where s.emp_no=e.emp_no and s.to_date='9999-01-01');

49、针对库中的所有表生成selectcount(*)对应的SQL语句

关键点:在 SQLite 系统表 sqlite_master 中可以获得所有表的索引,其中字段 name 是所有表的名字,而且对于自己创建的表而言,字段 type 永远是 'table'

SELECT "select count(*) from " || name || ";"  cnts
FROM sqlite_master WHERE type = 'table';

50、将employees表中的所有员工的last_name和first_name通过(')连接起来。

select last_name||"'"||first_name from employees;

51、查找字符串'10,A,B' 中逗号','出现的次数cnt。

select (length('10,A,B') - length(replace('10,A,B',',',''))) cnt;

52、获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列

select first_name from employees order by substr(first_name,-2);

53、按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees

本题要用到SQLite的聚合函数group_concat(X,Y),其中X是要连接的字段,Y是连接时用的符号,可省略,默认为逗号。

select dept_no, group_concat(emp_no) employees from dept_emp group by dept_no;

54、查找排除当前最大、最小salary之后的员工的平均工资avg_salary。

SELECT AVG(salary)  avg_salary FROM salaries 
WHERE to_date = '9999-01-01'
AND salary NOT IN (SELECT MAX(salary) FROM salaries WHERE to_date = '9999-01-01')
AND salary NOT IN (SELECT MIN(salary) FROM salaries WHERE to_date = '9999-01-01');

55、分页查询employees表,每5行一页,返回第2页的数据

select * from employees limit 5,5;

56、获取所有员工的emp_no、部门编号dept_no以及对应的bonus类型btype和recevied,没有分配具体的员工不显示

select d.emp_no, d.dept_no, eb.btype, eb.recevied from
employees e inner join dept_emp d on e.emp_no = d.emp_no
left join emp_bonus eb on e.emp_no=eb.emp_no;

57、使用含有关键字exists查找未分配具体部门的员工的所有信息。

SELECT * FROM employees WHERE NOT EXISTS 
(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no);

58、存在如下的视图:
create view emp_v as select * from employees where emp_no >10005;

获取employees中的行数据,且这些行也存在于emp_v中。注意不能使用intersect关键字。

select * from employees where emp_no>10005;

59、给出emp_no、first_name、last_name、奖金类型btype、对应的当前薪水情况salary以及奖金金额bonus。 bonus类型btype为1其奖金为薪水salary的10%,btype为2其奖金为薪水的20%,其他类型均为薪水的30%。 当前薪水表示to_date='9999-01-01'

select e.emp_no, e.first_name, e.last_name, eb.btype, s.salary,
(case eb.btype
when 1 then s.salary*0.1
when 2 then s.salary*0.2
else s.salary*0.3 end) bonus
from employees e inner join salaries s on e.emp_no = s.emp_no
inner join emp_bonus eb on e.emp_no = eb.emp_no
and s.to_date = '9999-01-01';

60、按照salary的累计和running_total,其中running_total为前面员工的salary累计和,其他以此类推。 具体结果如下Demo展示

select s1.emp_no, s1.salary,
(select sum(s2.salary) from salaries s2
where s2.emp_no <= s1.emp_no and s2.to_date='9999-01-01') running_total
from salaries s1 where s1.to_date='9999-01-01';

61、对于employees表中,给出按first_name升序排列的奇数行的first_name

select e1.first_name from employees e1
where (select count(*) from employees e2
where e1.first_name>=e2.first_name)%2=1;