题目19:

https://www.nowcoder.com/practice/5a7975fabe1146329cee4f670c27ad55?tpId=82&tqId=29771&tPage=1&rp=&ru=/ta/sql&qru=/ta/sql/question-ranking
题目描述
查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工

3个表
CREATE TABLE `departments` (
`dept_no` char(4) NOT NULL,
`dept_name` varchar(40) NOT NULL,
PRIMARY KEY (`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`));

图片说明

题解:

/*3个表,两次联结。里面的联结拿到employee的空或者不为空。*/
SELECT em.last_name, em.first_name, dp.dept_name
FROM (employees AS em LEFT JOIN dept_emp AS de 
      ON em.emp_no = de.emp_no)
LEFT JOIN departments AS dp 
ON de.dept_no = dp.dept_no

思路:
第一步,将员工表employees与员工-部门关系表dept_emp进行外连接left join,连接条件是员工编号对应,这样得到的连表包含所有的员工信息+对应的部门编号信息(如果员工未分配部门,则按照外连接规则,默认填写null);
第二步,将第一步中得到的连表,与部门信息表departments进行外连接,连接条件是部门编号对应,这样得到的新的连表即包含暂时没有分配部门的员工。第二步是将部门编号加入,为了不损失信息,左表全部要,因此还是需要使用左联接。


题目20:

https://www.nowcoder.com/practice/c727647886004942a89848e2b5130dc2?tpId=82&tqId=29772&tPage=1&rp=&ru=%2Fta%2Fsql&qru=%2Fta%2Fsql%2Fquestion-ranking
题目描述
查找员工编号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`));

图片说明

题解:

/*写法1:如果最后一次的工资调整为降薪,则此思路通不过,这个方法就不行了*/
select max(salary) - min(salary) AS growth
from salaries 
where emp_no = 10001 
/*写法2:严谨的方式是取最后的记录和第一次的记录做差值*/
SELECT ( 
(SELECT salary 
 FROM salaries 
 WHERE emp_no = 10001 
 ORDER BY to_date 
 DESC LIMIT 1) -
    (SELECT salary 
     FROM salaries 
     WHERE emp_no = 10001 
     ORDER BY to_date 
     ASC LIMIT 1)
) AS growth

题目21:

https://www.nowcoder.com/practice/fc7344ece7294b9e98401826b94c6ea5?tpId=82&tqId=29773&tPage=2&rp=&ru=%2Fta%2Fsql&qru=%2Fta%2Fsql%2Fquestion-ranking
题目描述
查找所有员工自入职以来的薪水涨幅情况,给出员工编号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`));

图片说明

题解:

/*写法1:两次联结,每次联结都拿到一种数据。入职的工资,当前的工资。再连接一次,做差求结果*/
SELECT a.emp_no, (a.salary-b.salary) AS growth
FROM (SELECT s.emp_no, s.salary 
      FROM employees e 
      LEFT JOIN salaries s 
      ON e.emp_no = s.emp_no 
      WHERE s.to_date = '9999-01-01') AS a
INNER JOIN (SELECT s.emp_no, s.salary 
            FROM employees e 
            LEFT JOIN salaries s 
            ON e.emp_no = s.emp_no 
            WHERE s.from_date = e.hire_date) AS b
ON a.emp_no = b.emp_no
ORDER BY growth
/*写法2:使用from并列查询*/
SELECT a.emp_no, (a.salary-b.salary) AS growth
FROM 
(SELECT s.emp_no, s.salary 
 FROM employees e, salaries s 
 WHERE e.emp_no = s.emp_no 
 AND s.to_date = '9999-01-01') AS a,
(SELECT s.emp_no, s.salary 
 FROM employees e, salaries s 
 WHERE e.emp_no = s.emp_no 
 AND s.from_date = e.hire_date) AS b
WHERE a.emp_no = b.emp_no
ORDER BY growth

题目22:

https://www.nowcoder.com/practice/6a62b6c0a7324350a6d9959fa7c21db3?tpId=82&tqId=29774&tPage=2&rp=&ru=%2Fta%2Fsql&qru=%2Fta%2Fsql%2Fquestion-ranking
题目描述
统计各个部门的工资记录数,给出部门编码dept_no、部门名称dept_name以及次数sum

CREATE TABLE `departments` (
`dept_no` char(4) NOT NULL,
`dept_name` varchar(40) NOT NULL,
PRIMARY KEY (`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 `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 de.dept_no, dp.dept_name, COUNT(s.salary) AS sum 
FROM (dept_emp AS de INNER JOIN salaries AS s 
      ON de.emp_no = s.emp_no) 
INNER JOIN departments AS dp 
ON de.dept_no = dp.dept_no 
GROUP BY de.dept_no

题目23:

https://www.nowcoder.com/practice/b9068bfe5df74276bd015b9729eec4bf?tpId=82&tqId=29775&tPage=2&rp=&ru=%2Fta%2Fsql&qru=%2Fta%2Fsql%2Fquestion-ranking
题目描述
对所有员工的当前(to_date='9999-01-01')薪水按照salary进行按照1-N的排名,相同salary并列且按照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 s1.emp_no, s1.salary, COUNT(DISTINCT s2.salary) AS rank
FROM salaries AS s1, salaries AS s2
WHERE s1.to_date = '9999-01-01'  
AND s2.to_date = '9999-01-01' 
AND s1.salary <= s2.salary     --这样能保证两个表的对应顺序不乱
GROUP BY s1.emp_no
ORDER BY s1.salary DESC, s1.emp_no ASC
/*写法2:上面的order by可以只用rank,或者salary,用一个两个条件均可*/

题目24:

https://www.nowcoder.com/practice/8fe212a6c71b42de9c15c56ce354bebe?tpId=82&tqId=29776&tPage=2&rp=&ru=%2Fta%2Fsql&qru=%2Fta%2Fsql%2Fquestion-ranking
题目描述
获取所有非manager员工当前的薪水情况,给出dept_no、emp_no以及salary ,当前表示to_date='9999-01-01'

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

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

题解:

4个表,员工(所有人),经理,普通雇员,薪水。求非manager员工当前的薪水情况
求出所有人薪水,最后not in 经理表。写法2对我而言更清晰。
/*写法1:*/
SELECT de.dept_no, s.emp_no, s.salary 
FROM (employees AS e INNER JOIN salaries AS s 
      ON s.emp_no = e.emp_no 
      AND s.to_date = '9999-01-01')
INNER JOIN dept_emp AS de 
ON e.emp_no = de.emp_no
WHERE de.emp_no NOT IN (SELECT emp_no 
                        FROM dept_manager 
                        WHERE to_date = '9999-01-01')
/*写法2:*/
SELECT de.dept_no, s.emp_no, s.salary 
FROM dept_emp AS de 
INNER JOIN salaries AS s 
ON s.emp_no = de.emp_no 
AND s.to_date = '9999-01-01'
WHERE de.emp_no NOT IN (SELECT emp_no 
                        FROM dept_manager 
                        WHERE to_date = '9999-01-01')