【面试】面试官啊!我真的很久都没写过SQL语句了,我现在就写!!

首先感谢自己修的福报,在面试的时候认识了小姐姐ghm,愿意听我逼逼叨复盘,你是我修来的福报,还有感谢火币的五位面试官,谢谢你们我学到了很多东西,谢谢你们给了我这次机会,先挖个坑慢慢填。我呢还是决定复习基础语法然后开始刷题。

数据库其他知识点,好文分享:MySQL优化/面试,看这一篇就够了

没有保存啊QAQ又得重写 

目录

1、基本查询语法

2、刷题

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

2.2 查找入职员工时间排名倒数第三的员工所有信息

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

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

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

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

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

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

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

2.10 获取所有非manager的员工emp_no

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

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

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

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

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

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

2.17 统计出当前各个title类型对应的员工当前(to_date='9999-01-01')薪水对应的平均工资。结果给出title以及平均工资avg。

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

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

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


1、基本查询语法

SELECT 查询输出的结果字段/函数调用结果
FROM 要查询的表
【WHERE 筛选条件】
【GROUP BY 按哪个字段分组】
【HAVING 再一次过滤条件】
【ORDER BY 排序的字段,可以多个 ACS/DESC】

2、刷题

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

最晚入职是标量查询,所以我选了子查询。

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 * #查询结果
FROM employees #在employees表中查询
WHERE hire_date # 筛选条件
=
(
    SELECT 
        max(hire_date)#最晚入职
    FROM
        employees
);

2.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`));
SELECT *  /*查询多有字段*/
FROM 
    "employees"
ORDER BY 
    hire_date DESC /*倒数第三个,则是倒叙的第三个*/
LIMIT 2,1; /*截取第三个人*/

2.3 查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号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`));

一开始我把dept_manager设为主表,发现1001号员工,他不是manager所以会产生对不上的情况,主要是查询employees的数据,所以应该把employees设为主表 ,也可以多加一个筛选条件就是让emp_no的值应该不为空。方法2中多加s.to_date的条件是因为salary的to_date可能不等于‘9999-01-01’,可能是‘1987-09-01’,所以要在两个表都加上to_date的限制条件。

/*方法1*/
SELECT s.*, dept_no
FROM salaries s
JOIN dept_manager d
ON d.'emp_no' = s.'emp_no'
WHERE d.'to_date' = '9999-01-01';


/*方法2*/
SELECT s.*, dept_no
FROM dept_manager d
JOIN salaries s
ON d.'emp_no' = s.'emp_no'
WHERE d.'to_date' = '9999-01-01'
AND s.'to_date' = '9999-01-01'
AND d.'emp_no' IS NOT NULL;

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

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 e.last_name, e.first_name, d.dept_no
FROM `dept_emp` d
JOIN `employees` e
ON e.`emp_no` = d.`emp_no`;

 2.5 查找所有员工的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 e.last_name, e.first_name, d.dept_no
FROM employees e
LEFT JOIN dept_emp d
ON e.`emp_no` = d.`emp_no`;

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

查找入职薪水情况,第一时间想到薪水可以对应多个的员工,入职时间就是最小的日期,正好salary已经拥有两个查询结果,所以只需要用到salary表即可,每一个员工都有入职薪水,所以可以按照员工编号进行分组,然后找出from_date最小的就是入职时间,对应的就是入职薪水。

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`));

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

用emp_no进行分组,然后算每一项有多少条数据命名为t,最后筛选出t大于15的即可。

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(*) t
FROM salaries
GROUP BY emp_no
HAVING t > 15;

2.8 找出所有员工当前(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`));
SELECT DISTINCT salary
FROM salaries
WHERE to_date='9999-01-01'
ORDER BY salary DESC;

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

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
JOIN salaries s
ON d.emp_no=s.emp_no
AND d.to_date=s.to_date
AND d.to_date='9999-01-01'

一开始我也是想用left join因为查询的是所有的manager,但是有没有manager是没有薪资的呢?我一直都想不明白,后来找到了一个人他在‘9999-01-01’这一天是没有薪资,因为他‘2000’年已经辞职了。所以用了INNER JOIN

 所以这是方法2:

SELECT dept_no, d.emp_no, salary
FROM dept_manager d
JOIN salaries s
ON d.emp_no=s.emp_no
AND d.to_date=s.to_date
AND d.to_date='9999-01-01'
WHERE d.to_date ='9999-01-01';

2.10 获取所有非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`));
SELECT emp_no
FROM employees
WHERE emp_no NOT IN (
    SELECT emp_no
    FROM dept_manager
)

做题做的比较慢,总结一下方法,只需要读一次题目即可。

  • 首先是看输出而不是看题目,快速确定select的内容。
  • 查看select的关键字都在那个表,考虑是否要关联,尽量不要关联。
  • 看最下面的主键,确定ON连接条件。
  • 再读一次题目,看有没有遗漏筛选条件。

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

此题有两个主键,首先是确定同一个部门员工是对应该部门的经理,所以ON的内容应该是比较‘dept_no’。其次是两表都要对应相同的时间。又因为题目中说好manger是自己的不显示就是暗示用inner join。

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 e.emp_no emp_no,m.emp_no manager_no
FROM dept_emp e
JOIN dept_manager m
ON e.dept_no = m.dept_no
WHERE e.to_date='9999-01-01'
AND m.to_date='9999-01-01'
AND m.emp_no <> e.emp_no;

2.12 获取所有部门中当前员工薪水最高的相关信息,给出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`));
SELECT d.dept_no, s.emp_no, MAX(salary) salary
FROM salaries s
JOIN dept_emp d
ON d.emp_no = s.emp_no
WHERE d.`to_date` = '9999-01-01'
AND s.`to_date` = '9999-01-01'
GROUP BY d.dept_no;

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

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);
SELECT title, COUNT(*) t
FROM titles
GROUP BY title
HAVING t>=2;

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

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);

同一个员工可以有多个title

SELECT title,COUNT(DISTINCT emp_no) t
FROM titles
GROUP BY title
HAVING t>=2;

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

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 *
FROM employees e
WHERE emp_no%2 = 1
ORDER BY hire_date DESC;

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

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`));

还有一种写法 MOD(emp_no, 2)相当于emp_no % 2 

SELECT *
FROM employees e
WHERE emp_no%2 = 1
ORDER BY hire_date DESC;

 2.17 统计出当前各个title类型对应的员工当前(to_date='9999-01-01')薪水对应的平均工资。结果给出title以及平均工资avg。

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 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);
SELECT t.title, AVG(s.salary)
FROM salaries s
JOIN titles t
ON t.emp_no = s.emp_no
AND t.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'
GROUP BY title;

2.18 获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水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`));
SELECT emp_no, salary
FROM salaries
WHERE to_date = '9999-01-01'
ORDER BY salary DESC
LIMIT 1,1;

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

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 `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`));

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

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`));
SELECT e.emp_no, (st.salary-sf.salary) growth
FROM employees e

    JOIN salaries st
    ON e.emp_no = st.emp_no
    AND st.to_date = '9999-01-01'

    JOIN salaries sf
    ON e.emp_no = sf.emp_no
    AND sf.to_date = e.hire_date

ORDER BY growth ASC;

审核:@Unyielding_L

发布了46 篇原创文章 · 获赞 75 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_38875300/article/details/102615766