MySQL练习(1)——牛客网[xiaoshun]

1、牛客网网址mysql

https://www.nowcoder.com/ta/sql,一共76道真题。sql

PS:不要过于相信在线编译器!!!作完每一题要记得看各位网友大神解读和总结。express

2、题目函数

一、查找最晚入职员工的全部信息,为了减轻入门难度,目前全部的数据里员工入职的日期都不是同一天(sqlite里面的注释为--,mysql为comment)
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,  -- '员工编号'
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));性能

解题:spa

(1)假设员工入职的日期都不是同一天,日期降序排序后,直接截取第一条数据便可。code

select * from employees order by hire_date desc limit 1;

  limit m,n:m为起始索引位置(索引从0开始),日后获取n行数据。如limit 6,10 获取第7行到16行数据。另外一种写法:limit n offset msqlite

  limit 语句运行顺序排到最后,由于它是从结果集中截取部分行数。blog

(2)假设员工入职的日期有可能同一天。排序

select *
from employees
where hire_date = (
    select max(hire_date)
    from employees);
#1.用子查询获取最迟入职日期;
#2.把入职日期等于最迟入职日期的全部全找出来。

二、查找入职员工时间排名倒数第三的员工全部信息,为了减轻入门难度,目前全部的数据里员工入职的日期都不是同一天
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题:

(1)假设员工入职的日期都不是同一天

select * from employees order by hire_date desc limit 2,1;
# 直接降序排序获取第三行记录便可

(2)假设员工入职的日期有可能同一天

select *
from employees
where hire_date=(
    select distinct hire_date
    from employees
    order by hire_date desc
    limit 1 offset 2
);
#1.先用distinct把重复的日期去重,获得的日期都是惟一的
#2.再排序后,用limit获取倒数第三天入职的日期
#3.最后把入职日期等于倒数第三天日期的员工信息所有获取

三、

查找各个部门当前(dept_manager.to_date='9999-01-01')领导当前(salaries.to_date='9999-01-01')薪水详情以及其对应部门编号dept_no
(注:请以salaries表为主表进行查询,输出结果以salaries.emp_no升序排序,而且请注意输出结果里面dept_no列是最后一列)
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL, -- '员工编号',
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL, -- '部门编号'
`emp_no` int(11) NOT NULL, --  '员工编号'
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

解题:

select sa.*, dm.dept_no
from  salaries as sa
inner join dept_manager as dm
on dm.emp_no = sa.emp_no
where sa.to_date='9999-01-01'
and dm.to_date='9999-01-01'
order by sa.emp_no asc;
# 考察表的内链接和一些实际状况业务的了解

四、查找全部已经分配部门的员工的last_name和first_name以及dept_no(请注意输出描述里各个列的先后顺序)
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

解题:

select last_name, first_name, dept_no
from employees e
inner join dept_emp d
on e.emp_no = d.emp_no
where dept_no is not null;
# 考察表内链接,不用指定dept_no是否为null,由于内链接中,任何一边有缺失数据就不会显示。

五、查找全部员工的last_name和first_name以及对应部门编号dept_no,也包括暂时没有分配具体部门的员工(请注意输出描述里各个列的先后顺序)
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));

select last_name,first_name,dept_no
from employees e
left join dept_emp d
on e.emp_no = d.emp_no;
#即便没有分配部门的员工也要显示,意味着employees表中全部emp_no都要显示,无论dept_emp表的对应dept_no是否缺失。考察左链接

多表链接查询知识点总结:

表1 inner join 表2  两边表同时有对应的数据,即任何一边有缺失数据就不显示;

主 left join 从    左边主表的数据所有读取,右边从边无对应数据的填充NULL值;

从 right join 主    反之;

 

六、查找全部员工入职时候的薪水状况,给出emp_no以及salary, 并按照emp_no进行逆序(请注意,一个员工可能有屡次涨薪的状况)
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题:

(1)表链接

select e.emp_no, s.salary
from employees e
inner join salaries s
on e.emp_no = s.emp_no
where s.from_date = e.hire_date
order by e.emp_no desc;
# 1.有涨薪或者降薪,说明salaries表中的每个emp_no至少有一个,薪水变过就有重复值。
# 2.只要from_date等于入职日期hire_date,薪水就是入职时的薪水。

(2)分组以后求日期最小值

select emp_no,salary
from salaries
group by emp_no
having min(from_date)
order by emp_no desc;
# 1.先用emp_no分组,获得每一个员工分组数据
# 2.再用having对每一个分组求最先日期,即刚入职的日期,不能求最小工资,由于员工有可能被降薪。
# 3.数据量大时,不建议用分组查询,由于having以后,程序会在每一个分组表中在遍历一遍,可能致使性能不佳。

七、查找薪水变更超过15次的员工号emp_no以及其对应的变更次数t
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题:

select emp_no,count(*) as t
from salaries
group by emp_no
having count(*) > 15;
# 考察点是分组统计查询,

分组聚合筛选查询知识点概括:

语法:
SELECT column1, column2, ... column_n, aggregate_function (expression),constant
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n
HAVING condition1 ... condition_n;

重点:

  • 分组后SELECT后能够出现:聚合字段(即group by后出现的字段)、集合函数输入值aggregate_function (expression)、常量。必须严格准守吖!否则错了也不知道;

  (12题,有典型的错误例子。)

  • having语句弥补了where关键字不能与与聚合函数联合使用的不足,可是要注意的是,having语句筛选的是分组,而不是分组中的某行记录;
  • where筛选的是原表,having是对各个分组表进行筛选判断,因此尽可能在where中把原表筛选到最小,分组后每一个表筛选遍历的速度就会加快了。

八、找出全部员工当前(to_date='9999-01-01')具体的薪水salary状况,对于相同的薪水只显示一次,并按照逆序显示
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题:

(1)distinct关键字排除重复

select distinct salary
from salaries
where to_date='9999-01-01'
order by salary desc;
# distinct 多列去重时,只有全部列的信息彻底一致才认为时重复的。

(2)用group by去重,听说数据量很大时,效率比较高

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

九、获取全部部门当前(dept_manager.to_date='9999-01-01')manager的当前(salaries.to_date='9999-01-01')薪水状况,给出dept_no, emp_no以及salary(请注意,同一我的可能有多条薪水状况记录)
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));

解题:

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

十、获取全部非manager的员工emp_no
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,

PRIMARY KEY (`emp_no`));
解题:
(1)左外链接
select e.emp_no
from employees e
left join dept_manager d
on e.emp_no = d.emp_no
where d.dept_no is null;
# 1.假如员工不是manager,那么dept_no字段应该为null
# 2.经过左链接的方式,使不是manager的dept_no字段为null,再筛选便可

(2)子查询

select emp_no
from employees
where emp_no not in(
    select d.emp_no
    from dept_manager d
    inner join employees e
    on d.emp_no = e.emp_no
);
# 1.先用子查询查出是manger的emp_no
# 2.再判断员工emp_no不在manger的emp_no里面便可
# 3.子查询能够直接用select emp_no from dept_manager,毕竟dept_manager这个表存的是manage的信息。

十一、获取全部员工当前的(dept_manager.to_date='9999-01-01')manager,若是员工是manager的话不显示(也就是若是当前的manager是本身的话结果不显示)。输出结果第一列给出当前员工的emp_no,第二列给出其manager对应的emp_no。
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL, -- '全部的员工编号'
`dept_no` char(4) NOT NULL, -- '部门编号'
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL, -- '部门编号'
`emp_no` int(11) NOT NULL, -- '经理编号'
`from_date` date NOT NULL,
`to_date` date NOT NULL,

PRIMARY KEY (`emp_no`,`dept_no`));
解题:
select de.emp_no, dm.emp_no as manager_no
from dept_emp de
inner join dept_manager dm
on dm.dept_no = de.dept_no
where de.emp_no <> dm.emp_no
and dm.to_date='9999-01-01'
and de.to_date='9999-01-01';
# 1.两表内链接后,只有manager的de.emp_no和dm.emp_no是同样的,用where筛选掉便可。
# 2.由于部门的manager有可能会离职或者更换,要保证manage和普通员工都在同一时间在同一部门才能构成从属关系。两个跨时空的人恋爱会很惨的!!!

 十二、获取全部部门中当前(dept_emp.to_date = '9999-01-01')员工当前(salaries.to_date='9999-01-01')薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门升序排列。
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,

PRIMARY KEY (`emp_no`,`from_date`));
相关文章
相关标签/搜索