Fighting——Day3

今天打算复习数据库SQL,计划完成牛客网上的数据库SQL实战30道题!

下面给出"员工表"的SQL创建语句:

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`));              // 主键为员工号

下面给出"员工_部门表"的SQL创建语句:

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`));    // 主键(员工号, 部门号)

下面给出"部门经理表"和"薪水详情表"的SQL创建语句:

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 *
from employees
where hire_date = (
    select max(hire_date)
    from employees
)

该题是要查询表中最晚入职的员工信息,通过子查询语句select max(hire_date) from employees即可获取表中最晚入职的hire_date字段的值,从而作为主查询语句的where判断条件,进而完成整体查询语句的设计。

  • 查找入职员工时间排名倒数第三的员工所有信息
select *
from employees
order by hire_date desc
limit 2,1

该题是要查询表中入职时间倒数第三的员工信息,即倒数第三个入职的员工信息,我们通过order by语句以hire_date为排序字段(注意这里必须采用desc排序方式,因为这样才可确定待查询员工为排序后表中第三行位置),此时表中的员工信息以入职时间,由大到小排列,在利用limit语句获取第三行数据limit 2,1,进而完成整体查询语句的设计。

  • 查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no
select salaries.*, dept_manager.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'

该题是要考察多表关联查询的语句,其中部门经理表与薪水详情表的关联字段为emp-no,并且查询要求为当前领导当前薪水,故在增加where语句当中增加判断条件salaries.to_date = '9999-01-01' and dept_manager.to_date = '9999-01-01',从而完成整体查询语句的设计。

  • 查找所有已经分配部门的员工的last_name,first_name以及部门号dept_no
select employees.last_name, employees.first_name, dept_emp.dept_no
from dept_emp, employees
where dept_emp.emp_no = employees.emp_no

如上述SQL语句,没有什么可以解释的了。

  • 查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工
select employees.last_name, employees.first_name, dept_emp.dept_no
from employees left join dept_emp on employees.emp_no = dept_emp.emp_no;

简单的左连接,如上述SQL语句,没有什么可以解释的了。

  • 查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序
select employees.emp_no, salaries.salary
from employees, salaries
where employees.emp_no = salaries.emp_no 
and employees.hire_date = salaries.from_date
order by employees.emp_no desc;

员工表与薪水详情表,两表连接,关联字段为emp_no,注意查询需求为员工入职时的薪水情况,因此需增加判断条件employees.hire_date = salaries.from_date,其次要求查询结果按照emp_no进行逆序排序,因此采用order by语句并采用desc逆序排序方式。

  • 查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t
select emp_no, count(*) as t
from salaries
group by emp_no
having t > 15;

这里就是一个简单的group by语句分组,再用having语句做判断条件,需要注意的是where语句的执行是在group by语句之前,而having语句的执行是在group by之后,因此这里采用having语句做判断。

  • 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示
select distinct(salary)
from salaries
where to_date = '9999-01-01'
order by salary desc;

distinct的使用,如上述SQL语句,没有什么可以解释的了。

  • 获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01'
select dept_manager.dept_no, dept_manager.emp_no, salaries.salary
from dept_manager, salaries
where dept_manager.emp_no = salaries.emp_no 
and dept_manager.to_date = '9999-01-01'
and salaries.to_date = '9999-01-01'

感觉这个题,不就是前面的那道题吗,这个题一定是在卖萌。

  • 获取所有非manager的员工emp_no
select employees.emp_no
from employees left join dept_manager on employees.emp_no = dept_manager.emp_no
where dept_manager.emp_no is null;

本来这个题就是考察两个结果集的差集,但是由于不支持except语法,这里采用employees表左连接dept_manager表,并且选取其中dept_manager.emp_no为空的行记录,这样就可以从employees表中筛选出非manager的员工了,算是左连接的一种使用技巧吧。

  • 获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。
select dept_emp.emp_no, dept_manager.emp_no
from dept_emp, dept_manager
where dept_emp.dept_no = dept_manager.dept_no
and dept_emp.emp_no <> dept_manager.emp_no
and dept_emp.to_date = '9999-01-01'
and dept_manager.to_date = '9999-01-01'

理清查询需求,逐步写完where语句中的判断条件,便可轻松解决。

  • 获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary
select dept_emp.dept_no, dept_emp.emp_no, max(salaries.salary)
from dept_emp, salaries
where dept_emp.emp_no = salaries.emp_no 
and dept_emp.to_date = '9999-01-01'
and salaries.to_date = '9999-01-01'
group by dept_emp.dept_no

这道题用到了select中的聚集函数,以及group by语句,实现了对分组记录的函数操作。从而筛选出每个部门当中薪水最高员工的记录,这道题其实具有参考意义。

下面给出"职位表"的SQL创建语句:

CREATE TABLE IF NOT EXISTS "titles" (    // 职位表
`emp_no` int(11) NOT NULL,               // 员工号  
`title` varchar(50) NOT NULL,            // 职位
`from_date` date NOT NULL,               // 起始日期
`to_date` date DEFAULT NULL);            // 结束日期
  • 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t
select title, count(*) as t
from titles
group by title
having t >= 2;

通过group by语句以title字段分组,并计算每组记录的个数t,采用having语句判断并筛选出所有组中记录个数大于等于2的组。

  • 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。注意对于重复的emp_no进行忽略。
select title, count(distinct emp_no) as t
from titles
group by title
having t >= 2;

在上一题的基础上,增加了限制条件,在同一组中重复的emp_no需要做去重处理,因此在count函数中的计数依据定义为distinct emp_no从而达到题意的要求。这道题相比于上一题更具有参考意义。

  • 查找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;

扫盲题,如上述SQL语句,没有什么可以解释的了。

  • 统计出当前各个title类型对应的员工当前薪水对应的平均工资。结果给出title以及平均工资avg。
select titles.title, avg(salaries.salary)
from titles, salaries
where titles.emp_no = salaries.emp_no
and titles.to_date = '9999-01-01'
and salaries.to_date = '9999-01-01'
group by titles.title

这道题做的时候检查了几次才通过,虽然这个题本身不难,但是提醒了一点,写SQL语句时,千万要注意字段与表的对应关系,切记切记!

  • 获取当前(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;

一次性通过,不想多说,如上述SQL语句,没有什么可以解释的了。

  • 查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by
select employees.emp_no, max(salaries.salary), employees.last_name, employees.first_name
from employees, salaries
where employees.emp_no = salaries.emp_no
and salaries.to_date = '9999-01-01'
and salaries.salary not in (
    select max(salary)
    from salaries
    where to_date = '9999-01-01'
)

此题妙啊,彰显了我的智慧,一次提交正确嘻嘻!同样在上一题的基础上,增加了限定条件不准使用order by,凭借我超强的意识,自然而然的想到了max,子查询先在salaries表中获取最大工资的值,然后在父查询中的where判断中使得salaries.salary字段不等于最大的薪水值,此时父查询中的max便实现了筛选排名第二多的员工记录信息。

计划做30道题来着的,只完成了20道,没关系,完成了计划的66.67%,明天早起继续做!

发布了37 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42570248/article/details/90314547