【力扣 + 牛客 | SQL题 | 每日6题】牛客SQL热题 + 力扣hard

1. 牛客SQL热题206:获取每个部门中当前员工薪水最高的相关信息

1.1 题目:

描述

有一个员工表dept_emp简况如下:

|--------|---------|------------|------------|
| emp_no | dept_no | from_date | to_date |
| 10001 | d001 | 1986-06-26 | 9999-01-01 |
| 10002 | d001 | 1996-08-03 | 9999-01-01 |
| 10003 | d002 | 1996-08-03 | 9999-01-01 |

有一个薪水表salaries简况如下:

|--------|--------|------------|------------|
| emp_no | salary | from_date | to_date |
| 10001 | 88958 | 2002-06-22 | 9999-01-01 |
| 10002 | 72527 | 2001-08-02 | 9999-01-01 |
| 10003 | 92527 | 2001-08-02 | 9999-01-01 |

获取每个部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary,按照部门编号dept_no升序排列,以上例子输出如下:

|---------|--------|-----------|
| dept_no | emp_no | maxSalary |
| d001 | 10001 | 88958 |
| d002 | 10003 | 92527 |

示例1
sql 复制代码
输入:

drop table if exists  `dept_emp` ; 
drop table if exists  `salaries` ; 
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`));
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1996-08-03','9999-01-01');

INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,92527,'2001-08-02','9999-01-01');
复制输出:

d001|10001|88958
d002|10003|92527

1.2 思路:

一个相关子查询即可搞定。

1.3 题解:

sql 复制代码
with tep1 as (
    -- 两表连接
    select t1.emp_no, dept_no, salary
    from dept_emp t1
    join salaries t2
    on t1.emp_no = t2.emp_no
)


select dept_no, emp_no, salary maxSalary
from tep1 t1
where salary = (
    -- 相关子查询,查找外部记录所在部门的最高薪水
    select max(salary)
    from tep1 t2
    where t1.dept_no = t2.dept_no
)
order by dept_no

2. 牛客SQL热题205:获取所有员工当前的manager

2.1 题目:

描述

有一个员工表dept_emp简况如下:

|--------|---------|------------|------------|
| emp_no | dept_no | from_date | to_date |
| 10001 | d001 | 1986-06-26 | 9999-01-01 |
| 10002 | d001 | 1996-08-03 | 9999-01-01 |
| 10003 | d002 | 1995-12-03 | 9999-01-01 |

第一行表示为员工编号为10001的部门是d001部门。

有一个部门经理表dept_manager简况如下:

|---------|--------|------------|------------|
| dept_no | emp_no | from_date | to_date |
| d001 | 10002 | 1996-08-03 | 9999-01-01 |
| d002 | 10003 | 1990-08-05 | 9999-01-01 |

第一行表示为d001部门的经理是编号为10002的员工。

获取所有的员工和员工对应的经理,如果员工本身是经理的话则不显示,以上例子如下:

|--------|---------|
| emp_no | manager |
| 10001 | 10002 |

示例1
sql 复制代码
输入:

drop table if exists  `dept_emp` ; 
drop table if exists  `dept_manager` ; 
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`));
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01');
INSERT INTO dept_emp VALUES(10003,'d002','1995-12-03','9999-01-01');
INSERT INTO dept_manager VALUES('d001',10002,'1996-08-03','9999-01-01');
INSERT INTO dept_manager VALUES('d002',10003,'1990-08-05','9999-01-01');
复制输出:

10001|10002

2.2 思路:

秒。

2.3 题解:

sql 复制代码
select t1.emp_no emp_no, t2.emp_no manager
from dept_emp t1
join dept_manager t2
on t1.dept_no = t2.dept_no 
and t1.emp_no <> t2.emp_no

3. 牛客SQL热题199:查找所有员工的last_name和first_name以及对应部门编号的dept_no

3.1 题目:

描述

有一个员工表,employees简况如下:

|--------|------------|------------|-----------|--------|------------|
| emp_no | birth_date | first_name | last_name | gender | hire_date |
| 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 |
| 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 |
| 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 |
| 10004 | 1954-05-01 | Christian | Koblick | M | 1986-12-01 |

有一个部门表,dept_emp简况如下:

|--------|---------|------------|------------|
| emp_no | dept_no | from_date | to_date |
| 10001 | d001 | 1986-06-26 | 9999-01-01 |
| 10002 | d002 | 1989-08-03 | 9999-01-01 |

请你查找所有已经分配部门的员工的last_name和first_name以及dept_no,也包括暂时没有分配具体部门的员工,以上例子如下:

|-----------|------------|---------|
| last_name | first_name | dept_no |
| Facello | Georgi | d001 |
| Simmel | Bezalel | d002 |
| Bamford | Parto | NULL |
| Koblick | Chirstian | NULL |

示例1
sql 复制代码
输入:

drop table if exists  `dept_emp` ; 
drop table if exists  `employees` ; 
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`));
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d002','1996-08-03','9999-01-01');
INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26');
INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21');
INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28');
INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01');
复制输出:

Facello|Georgi|d001
Simmel|Bezalel|d002
Bamford|Parto|None
Koblick|Chirstian|None

3.2 思路:

秒。

3.3 题解:

sql 复制代码
select last_name , first_name , dept_no 
from employees t1
left join dept_emp t2
on t1.emp_no = t2.emp_no 

4. 牛客SQL热题198:查找所有已经分配部门的员工的last_name和first_name以及dept_no

4.1 题目:

描述

有一个员工表,employees简况如下:

|--------|------------|------------|-----------|--------|------------|
| emp_no | birth_date | first_name | last_name | gender | hire_date |
| 10001 | 1953-09-02 | Georgi | Facello | M | 1986-06-26 |
| 10002 | 1964-06-02 | Bezalel | Simmel | F | 1985-11-21 |
| 10003 | 1959-12-03 | Parto | Bamford | M | 1986-08-28 |
| 10004 | 1954-05-01 | Christian | Koblick | M | 1986-12-01 |

有一个部门表,dept_emp简况如下:

|--------|---------|------------|------------|
| emp_no | dept_no | from_date | to_date |
| 10001 | d001 | 1986-06-26 | 9999-01-01 |
| 10002 | d002 | 1989-08-03 | 9999-01-01 |

请你查找所有已经分配部门的员工的last_name和first_name以及dept_no,未分配的部门的员工不显示,以上例子如下:

|-----------|------------|---------|
| last_name | first_name | dept_no |
| Facello | Georgi | d001 |
| Simmel | Bezalel | d002 |

示例1
sql 复制代码
输入:

drop table if exists  `dept_emp` ; 
drop table if exists  `employees` ; 
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`));
INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01');
INSERT INTO dept_emp VALUES(10002,'d002','1996-08-03','9999-01-01');
INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26');
INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21');
INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28');
INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01');
复制输出:

Facello|Georgi|d001
Simmel|Bezalel|d002

4.2 思路:

秒。

4.3 题解:

sql 复制代码
select last_name , first_name , dept_no 
from employees t1
join dept_emp t2
on t1.emp_no  = t2.emp_no 

5. 牛客SQL热题197:查找当前薪水详情以及部门编号dept_no

5.1 题目:

描述

有一个全部员工的薪水表salaries简况如下:

|--------|--------|------------|------------|
| emp_no | salary | from_date | to_date |
| 10001 | 88958 | 2002-06-22 | 9999-01-01 |
| 10002 | 72527 | 2001-08-02 | 9999-01-01 |
| 10003 | 43311 | 2001-12-01 | 9999-01-01 |

有一个各个部门的领导表dept_manager简况如下:

|---------|--------|------------|
| dept_no | emp_no | to_date |
| d001 | 10001 | 9999-01-01 |
| d002 | 10003 | 9999-01-01 |

请你查找各个部门当前领导的薪水详情以及其对应部门编号dept_no,输出结果以salaries.emp_no升序排序,并且请注意输出结果里面dept_no列是最后一列,以上例子输出如下:

|--------|--------|------------|------------|---------|
| emp_no | salary | from_date | to_date | dept_no |
| 10001 | 88958 | 2002-06-22 | 9999-01-01 | d001 |
| 10003 | 43311 | 2001-12-01 | 9999-01-01 | d002 |

示例1
sql 复制代码
输入:

drop table if exists  `salaries` ; 
drop table if exists  `dept_manager` ; 
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`));
INSERT INTO dept_manager VALUES('d001',10002,'9999-01-01');
INSERT INTO dept_manager VALUES('d002',10006,'9999-01-01');
INSERT INTO dept_manager VALUES('d003',10005,'9999-01-01');
INSERT INTO dept_manager VALUES('d004',10004,'9999-01-01');
INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01');
INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10003,43311,'2001-12-01','9999-01-01');
INSERT INTO salaries VALUES(10004,74057,'2001-11-27','9999-01-01');
INSERT INTO salaries VALUES(10005,94692,'2001-09-09','9999-01-01');
INSERT INTO salaries VALUES(10006,43311,'2001-08-02','9999-01-01');
INSERT INTO salaries VALUES(10007,88070,'2002-02-07','9999-01-01');
复制输出:

10002|72527|2001-08-02|9999-01-01|d001
10004|74057|2001-11-27|9999-01-01|d004
10005|94692|2001-09-09|9999-01-01|d003
10006|43311|2001-08-02|9999-01-01|d002

5.2 思路:

秒。

5.3 题解:

sql 复制代码
select t1.emp_no, salary, from_date, t1.to_date, dept_no
from salaries t1
join dept_manager t2
on t1.emp_no = t2.emp_no
order by t1.emp_no

6. 力扣hard题615:平均薪资:部门与公司比较

6.1 题目:

表:Salary

复制代码
+-------------+------+
| 列名        | 类型 |
+-------------+------+
| id          | int  |
| employee_id | int  |
| amount      | int  |
| pay_date    | date |
+-------------+------+
在 SQL 中,id 是该表的主键列。
该表的每一行表示一个员工一个月的薪资。
employee_id 是来自 Employee 表的外键(reference 列)。

表: Employee

复制代码
+---------------+------+
| 列名          | 类型 |
+---------------+------+
| employee_id   | int  |
| department_id | int  |
+---------------+------+
在 SQL 中,employee_id 是该表的主键列。
该表的每一行表示一个员工所属的部门。

找出各个部门员工的平均薪资与公司平均薪资之间的比较结果(更高 / 更低 / 相同)。

任意顺序 返回结果表。

结果格式如下所示。

示例 1:

复制代码
输入:
Salary 表:
+----+-------------+--------+------------+
| id | employee_id | amount | pay_date   |
+----+-------------+--------+------------+
| 1  | 1           | 9000   | 2017/03/31 |
| 2  | 2           | 6000   | 2017/03/31 |
| 3  | 3           | 10000  | 2017/03/31 |
| 4  | 1           | 7000   | 2017/02/28 |
| 5  | 2           | 6000   | 2017/02/28 |
| 6  | 3           | 8000   | 2017/02/28 |
+----+-------------+--------+------------+
Employee 表:
+-------------+---------------+
| employee_id | department_id |
+-------------+---------------+
| 1           | 1             |
| 2           | 2             |
| 3           | 2             |
+-------------+---------------+
输出:
+-----------+---------------+------------+
| pay_month | department_id | comparison |
+-----------+---------------+------------+
| 2017-02   | 1             | same       |
| 2017-03   | 1             | higher     |
| 2017-02   | 2             | same       |
| 2017-03   | 2             | lower      |
+-----------+---------------+------------+
解释:
在三月,公司的平均工资是 (9000+6000+10000)/3 = 8333.33...
部门 '1' 的平均薪资是 9000,因为该部门只有一个员工,其员工号为 '1'。因为 9000 > 8333.33,所以比较结果为 'higher'
部门 '2' 的平均薪资是(6000 + 10000)/ 2 = 8000,该平均薪资是员工号 '2' 和 '3' 的薪资的平均值。因为 8000 < 8333.33,比较结果为 'lower'。

根据同样的公式,对于二月份的平均薪资比较,结果为 'same',因为部门 '1' 和 '2' 都与公司的平均薪资相同,即为 7000。

6.2 思路:

两步走:

-- 先求出每个月公司的平均薪资

-- 然后以部门和月份分组,比较分组内的平均薪资与该月份公司的平均薪资的大小

6.3 题解:

sql 复制代码
-- 先求出每个月公司的平均薪资
with tep1 as (
    select substring(pay_date, 1, 7) pay_month , round(avg(amount), 4) avgs
    from Salary
    group by substring(pay_date, 1, 7)
), tep2 as (
    -- 多表连接
    select t2.employee_id , department_id, amount , substring(pay_date, 1, 7) pay_month 
    from Salary t1 
    join Employee t2 
    on t1.employee_id = t2.employee_id 
)

-- 然后以部门和月份分组,比较分组内的平均薪资与该月份公司的平均薪资的大小
-- 我没有用round过不了最后一个案例,但使用round函数就可以过了。
-- 我也不知道为什么。
select pay_month, department_id,
case when round(avg(amount), 4) > (select avgs from tep1 t2 where t1.pay_month = t2.pay_month)
then 'higher'
when round(avg(amount), 4) < (select avgs from tep1 t2 where t1.pay_month = t2.pay_month)
then 'lower'
else 'same'
end comparison 
from tep2 t1
group by pay_month, department_id
相关推荐
LCG元1 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
XH华3 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子4 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡4 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin4 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码4 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7245 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活5 小时前
理解支持向量机
算法·机器学习·支持向量机