牛客網數據庫SQL實戰剖析(1-10)

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

解題思路:根據入職時間倒序排序order by ... DESC,而後再取一條記錄,就是最晚入職的員工。html

select * from employees 
order by hire_date DESC limit 1;

這樣作有一個問題,hire_date是 date 類型,頗有可能多條記錄中是同一個時間入職的,因此說時間類型仍是用時間戳比較精切。mysql

來源:https://www.cnblogs.com/Jie-Jack/p/3793304.html

針對這道題目能夠使用 MAX() 函數,而後用一個子查詢。sql

select * from employees
where hire_date = (select MAX(hire_date) FROM employees);

MAX()先查詢出最晚入職的時間,而後再查詢出在最晚時間入職的全部員工。yii


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

解題思路:查詢入職時間倒數第三的,要先進行排序,再取三條記錄。MySQL中的結果集默認以正序排列,要逆序排列就要使用 DESC,取第三條則是使用limit優化

select * from employees
order by hire_date DESC 
limit 2,1;

3. 查找當前薪水詳情以及部門編號dept_no

查找各個部門當前(to_date='9999-01-01')領導當前薪水詳情以及其對應部門編號dept_nocode

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

解題思路:這是一個等值鏈接的題目,用員工編號emp_no 作關聯便可。htm

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

上面的SQL有一個優化的點,就是能夠用 s.to_date='9999-01-01' 再進行一次去重鎖定。修改以後的 SQL 以下所示:blog

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

吐槽:牛客網裏,表 dept_manager 用兩個字母的別名 dm,居然過不了...排序


4. 查找全部已經分配部門的員工的last_name和first_name以及dept_no

查找全部已經分配部門的員工的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`));

解題思路:這道題開始想到用一個子查詢,先查詢出全部部門id,做爲條件去查詢員工表。而後看到還須要查詢出部門表裏的dept_no ,因此以爲用外鏈接更加合適,用dept_emp 表做爲主表進行查詢。

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

5. 查找全部員工的last_name和first_name以及對應部門編號dept_no

查找全部員工的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 d.emp_no=e.emp_no;

6. 查找全部員工入職時候的薪水狀況

查找全部員工入職時候的薪水狀況,給出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`));

解題思路:這道題要考慮到,員工的入職時的薪水狀況,即他入職第一個月時的薪水,即employees.​hire_date=salaries.​from_date​​

select e.emp_no, s.salary
from employees e
join salaries s on e.emp_no=s.emp_no and e.hire_date = s.from_date
order by e.emp_no DESC;

7. 查找薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t

查找薪水漲幅超過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`)
);

解題思路:看到這道題第一反應是,這道題也太複雜了。由於薪水漲幅須要比較先後兩個月的薪水,若是薪水降低是不能算漲幅的。因此,用解題的思路,我以爲這道題不會這麼複雜,就大膽假設它默認一直漲薪的。

從應試的角度,我以爲它是要考察 group by...having...,也就是先經過 emp_no 進行分組,再過濾分組記錄數大於15的記錄

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

果真是這樣。不用糾結這道題的題意,知道考察點在group by...having...就好了。

MySQL having子句


8. 找出全部員工當前薪水salary狀況

找出全部員工當前(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`));

解題思路:這道題講到了,相同的薪水只顯示一次,就是讓咱們用 DISTINCT 去重。

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'

獲取全部部門當前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`));

解題思路:這道題先看錶結構,emp_no,dept_nodept_manager 表的主鍵,這就表示一個部門可能有多個領導,而後dept_manager 去關聯salaries 表查詢工資便可,限制條件是查詢當天的工資 s.to_date='9999-01-01';

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

可是我這樣寫,居然AC不過,導入數據後發現,查詢結果是這樣的,意思就是一個部門的一個領導,在同一天會有多份工資??

d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d001	10002	72527
d004	10004	40054
d004	10004	42283
d004	10004	42542
d004	10004	46065
d004	10004	48271
d004	10004	50594
d004	10004	52119
d004	10004	54693
d004	10004	58326

要再加一個查詢條件d.to_date='9999-01-01',看討論說是表示在職的經理。

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

10. 獲取全部非manager的員工emp_no

獲取全部非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`));

解題思路:查找不是 Manager 的員工,即 employees 左鏈接 dept_manager 以後,沒有在 dept_manager 表中查詢到記錄的員工。因此在關聯以後,判斷 d.dept_no IS NULL; 就是在 dept_manager 表中沒有數據的員工了。

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;
相關文章
相關標籤/搜索