目录

1 查找最晚入职员工的信息

2 查找入职第三晚的员工信息

3 查找当前薪水详情及部门编号

4 查找所有员工入职时的薪水情况

5 查找已分配员工姓名

6 查找员工姓名

7 查找涨薪找过15次的员工

8 找出所有员工当前薪水情况

9 获取当前部门所有manager的薪水情况

10 获取所有非manager的员工emp_no

11 获取当前员工的manager

12 获取当前薪水最高的员工信息

注:下面的解题中会发现后多INNER JOIN这种内联,其实不用写也没关系的。

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`));
输入描述:

输出描述:

示例1
输入

输出

 -- 查询语句 LIMIT 1 是LIMIT 0,1 表是从第0条数据开始取1条数据
SELECT * FROM employees ORDER BY hire_date DESC LIMIT 1;
-- 这个语句有问题在于只找到了一条记录,有可能当天会有好多人入职 -- 从表的日期中挑选出最大的就可以避免上述问题了
SELECT * FROM employees WHERE
hire_date=(SELECT MAX(hire_date) FROM employees)

其实对于max也可以用下面的代替:这个和下面查找第三晚的就很类似了

SELECT *
FROM employees
WHERE hire_date=(SELECT hire_date FROM employees ORDER BY hire_date DESC LIMIT 1)

2 查找入职第三晚的员工信息

在上面一个问题的前提下找到第三晚入职的员工

 -- distinct 是过滤掉重复的,因为前面的可能日期相同的不止一个,但这样同样会有一个问题
-- 采用下面的方法也是只能挑出来一个信息,当倒数第三个日期有好几个时就会出现错误
SELECT *FROM employees WHERE
hire_date=(SELECT DISTINCT hire_date FROM employees ORDER BY hire_date DESC LIMIT 2,1);

3 查找当前薪水详情及部门编号

题目描述
查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no
输入描述:

输出描述:

 -- 根据输出表的信息确定salaries是主表
SELECT s.*,d.dept_no -- 选择salaries表和dept_manager的dept_no列
FROM salaries AS s JOIN dept_manager AS d -- 两个as相当于对表重命名,所以一开始才可以直接用s和d表示两个表
ON s.emp_no=d.emp_no -- on在创建临时表的限制条件,一般两个表链接时多用
WHERE s.to_date='9999-01-01' AND d.to_date='9999-01-01' -- 临时表生成后的限制
-- 执行顺序为先 on再where -- 可以用下面这个代码试试会产生什么情况
SELECT d.*,s.salary FROM salaries AS s JOIN dept_manager AS d
ON s.emp_no=d.emp_no
WHERE s.to_date='9999-01-01' AND d.to_date='9999-01-01'

上面的代码但在实际开发中是不推荐使用的,因为数据库在使用中应尽量减少物理连接,使用逻辑连接,因此多使用where语句来完成关联,此外使用where在性能上也要比使用join连接快

SELECT s.*,d.dept_no
FROM salaries AS s, dept_manager AS d
WHERE s.emp_no = d.emp_no
AND s.to_date='9999-01-01'
AND d.to_date='9999-01-01'

4 查找所有员工入职时的薪水情况

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

输入描述:

输出描述:

 /*
此题应注意以下四个知识点:
1、由于测试数据中,salaries.emp_no 不唯一(因为号码为 emp_no 的员工会有多次涨薪的可能,所以在 salaries 中对应的记录不止一条),employees.emp_no 唯一,即 salaries 的数据会多于 employees,因此需先找到 employees.emp_no 在 salaries 表中对应的记录salaries.emp_no,则有限制条件 e.emp_no = s.emp_no
2、根据题意注意到 salaries.from_date 和 employees.hire_date 的值应该要相等,因此有限制条件 e.hire_date = s.from_date
3、根据题意要按照 emp_no 值逆序排列,因此最后要加上 ORDER BY e.emp_no DESC
4、为了代码良好的可读性,运用了 Alias 别名语句,将 employees 简化为 e,salaries 简化为s,即 employees AS e 与 salaries AS s,其中 AS 可以省略
*/ SELECT e.emp_no,s.salary FROM employees AS e INNER JOIN salaries AS s -- JOIN In 就是JOIN内连接
ON e.emp_no=s.emp_no AND e.hire_date=s.from_date -- 要找到是入职信息
ORDER BY e.emp_no DESC -- 降序排列 # 方法二:直接用逗号并列查询两张表
SELECT e.emp_no, s.salary FROM employees AS e, salaries AS s
WHERE e.emp_no = s.emp_no AND e.hire_date = s.from_date
ORDER BY e.emp_no DESC

5 查找已分配员工姓名

题目描述
查找所有已经分配部门的员工的last_name和first_name
输入描述:

输出描述:

直接查询即可:

SELECT e.last_name,e.first_name,d.dept_no
FROM dept_emp AS d, employees AS e
WHERE d.emp_no = e.emp_no

下面是看题目讨论中给出的一些方法,可以参考一下

 -- 采用内连接的方式
SELECT e.last_name,e.first_name,d.dept_no FROM dept_emp AS d
INNER JOIN employees AS e
ON e.emp_no = d.emp_no; -- 但此问题只要用自然连接就行了,两张表只有一列相同且属性也相同 SELECT e.last_name, e.first_name, d.dept_no
FROM dept_emp d NATURAL JOIN employees e;

6 查找员工姓名

题目描述
查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工
输入描述:

输出描述:

 /*
INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据。
*/ 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

7 查找涨薪找过15次的员工

题目描述
查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t
输入描述:

输出描述:

 /*
此题应注意以下四点:
1、用COUNT()函数和GROUP BY语句可以统计同一emp_no值的记录条数
2、根据题意,输出的涨幅次数为t,故用AS语句将COUNT(emp_no)的值转换为t
3、由于COUNT()函数不可用于WHERE语句中,故使用HAVING语句来限定t>15的条件
4、最后存在一个理解误区,涨幅超过15次,salaries中相应的记录数应该超过16(从第2条记录开始算作第1次涨幅),不过题目为了简单起见,将第1条记录当作第1次涨幅,所以令t>15即可
注意: 严格来说,下一条salary高于本条才算涨幅,但本题只要出现了一条记录就算一次涨幅,salary相同可以理解为涨幅为0,salary变少理解为涨幅为负
*/
-- group by 可以简单理解为分类汇总
SELECT emp_no, COUNT(emp_no) AS t FROM salaries
GROUP BY emp_no HAVING t > 15

8 找出所有员工当前薪水情况

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

输出描述:

 /*
对于distinct,groupby的性能。
数据量非常巨大时候,比如1000万中有300W重复数据,这时候的distinct的效率略好于group by;
对于相对重复量较小的数据量比如1000万中1万的重复量,用groupby的性能会远优于distnct
*/ SELECT salary FROM salaries WHERE to_date='9999-01-01' GROUP BY salary ORDER BY salary DESC;
-- 方法二:
SELECT DISTINCT salary FROM salaries WHERE to_date = '9999-01-01' ORDER BY salary DESC

9 获取当前部门所有manager的薪水情况

题目描述
获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01'
输入描述:

输出描述:

自己写的:

SELECT d.dept_no,d.emp_no,s.salary
FROM salaries AS s,dept_manager AS d
WHERE s.to_date='9999-01-01'
AND d.to_date='9999-01-01'
AND d.emp_no = s.emp_no
 SELECT d.dept_no, d.emp_no, s.salary
FROM salaries AS s INNER JOIN dept_manager AS d
ON d.emp_no = s.emp_no
AND d.to_date = '9999-01-01' AND s.to_date = '9999-01-01' -- 限制目前时间
 -- 下面是讨论中的内容,但我试了下没有order by到也通过了,可能这个本来就不是重要问题吧
-- 将连接语句改成 FROM dept_manager AS d INNER JOIN salaries AS s 后,结果通不过
-- 连接后按照前面的第一个 KEY 值排序,若 salaries 在前,则按照 s.emp_no 排序(因为限制条件为 d.emp_no = s.emp_no,
-- 所以对 s.emp_no 排序就是对d.emp_no 排序),输出跟参考答案一致,没问题;
-- 若 dept_manager 在前,则按照 d.dept_no排序,此时与参考答案不同,所以需要在末尾手动用 ORDER BY 对d.emp_no进行排序。 SELECT d.dept_no, d.emp_no, s.salary
FROM dept_manager AS d INNER JOIN salaries AS s
ON d.emp_no = s.emp_no
AND d.to_date = '9999-01-01'
AND s.to_date = '9999-01-01'
ORDER BY d.emp_no

10 获取所有非manager的员工emp_no

题目描述
获取所有非manager的员工emp_no
输入描述:

输出描述:

 -- 方法一:使用NOT IN选出在employees但不在dept_manager中的emp_no记录
SELECT emp_no FROM employees
WHERE emp_no NOT IN (SELECT emp_no FROM dept_manager)
-- 方法二:先使用LEFT JOIN连接两张表,再从此表中选出dept_no值为NULL对应的emp_no记录 SELECT emp_no FROM (SELECT * FROM employees LEFT JOIN dept_manager
ON employees.emp_no = dept_manager.emp_no)
WHERE dept_no IS NULL
-- 方法三:方法二的简版,使用单层SELECT语句即可 SELECT employees.emp_no FROM employees LEFT JOIN dept_manager
ON employees.emp_no = dept_manager.emp_no
WHERE dept_no IS NULL -- 方法四:使用集合运算 EXPECT 集合差运算 UNION 集合并运算 INTERSECT 集合交运算
SELECT employees.emp_no
FROM salaries
EXCEPT
SELECT dept_manager.emp_no
FROM dept_manager;

11 获取当前员工的manager

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

输出描述:

 /*
本题应注意以下三点:
1、用 INNER JOIN 连接两张表,因为要输出自己的经理,得知自己与经理的部门要相同,故有限制条件 de.dept_no = dm.dept_no
2、再用 WHERE 限制当前员工与当前经理的条件,即 dm.to_date 等于 '9999-01-01' 、de.to_date 等于 '9999-01-01' 、 de.emp_no 不等于 dm.emp_no
3、为了增强代码可读性,将 dept_emp 用别名 de 代替,dept_manager 用 dm 代替,最后根据题意将 de.emp_no 用别名 manager_no 代替后输出
*/
SELECT de.emp_no, dm.emp_no AS manager_no
FROM dept_emp AS de INNER JOIN dept_manager AS dm
ON de.dept_no = dm.dept_no
WHERE dm.to_date = '9999-01-01' AND de.to_date = '9999-01-01' AND de.emp_no <> dm.emp_no

在上面代码中也可以不用使用内联 INNER JOIN的。

12 获取当前薪水最高的员工信息

题目描述
获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary
输入描述:

输出描述:

 SELECT d.dept_no, s.emp_no, MAX(s.salary) AS salary
FROM salaries AS s INNER JOIN dept_emp AS 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 /*
有同学提出疑问,如果存在多条最大记录怎么办?而 MAX 函数根据不同数据库只选择最前一条或最后一条最大记录,其余记录均被忽略。此时解法如下:
1、创建两张表,一张为maxsalary,用于存放当前每个部门薪水的最大值;另一张为currentsalary,用于存放当前每个部门所有员工的编号和薪水;
2、限定条件为两张表的 dept_no 和 salary 相等,这样就可以找出当前每个部门所有薪水等于最大值的员工的相关信息了;
3、最后记得根据 currentsalary.dept_no 升序排列,输出与参考答案相同的记录表。
4、以下代码虽然很长,仔细一看都是基于上面的基础解法变化而来的,中心思想就是绕开 MAX 的特性限制,运用比较的方法选出多个相同的最大值。
*/ SELECT currentsalary.dept_no, currentsalary.emp_no, currentsalary.salary AS salary
FROM
#创建maxsalary表用于存放当前每个部门薪水的最大值
(SELECT d.dept_no, MAX(s.salary) AS salary
FROM salaries AS s INNER JOIN dept_emp AS 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) AS maxsalary,
#创建currentsalary表用于存放当前每个部门所有员工的编号和薪水
(SELECT d.dept_no, s.emp_no, s.salary
FROM salaries AS s INNER JOIN dept_emp AS d
ON d.emp_no = s.emp_no
WHERE d.to_date = '9999-01-01' AND s.to_date = '9999-01-01'
) AS currentsalary
#限定条件为两表的dept_no和salary均相等
WHERE currentsalary.dept_no = maxsalary.dept_no
AND currentsalary.salary = maxsalary.salary
#最后以currentsalary.dept_no排序输出符合要求的记录表
ORDER BY currentsalary.dept_no

0

最新文章

  1. Expression Blend创建自定义按钮
  2. &lt;&lt;&lt; List&lt;HashMap&lt;String, Object&gt;&gt; 及 HashMap&lt;String, Object&gt; 的用法
  3. Scrum 项目 6.0
  4. FZU5BOYS-Beta版本冲刺计划及安排
  5. Socket入门-获取服务器时间实例
  6. JQuery:JQuery 中的CSS()方法
  7. 5.2使用select,poll
  8. Selenium 使用方法小结
  9. ffmpeg常见命令
  10. Git版本管理:Windows下Git配置与使用指南 Gitlab
  11. HUD 2089 位数dp
  12. Java 多线程之龟兔赛跑(文件夹——读取文件——时间)
  13. production stage
  14. SQL语言的分类
  15. 事件冒泡以及onmouseenter 和 onmouseover 的不同
  16. linux项目部署常用命令
  17. Django之url定义和ORM框架的使用
  18. startActivityForResult的使用和用法
  19. 安卓开发笔记——GridView组件
  20. forget word out a~2

热门文章

  1. 【IDEA插件】—— 代码量统计工具Statistic
  2. python os系统
  3. Error starting daemon: error initializing graphdriver: devmapper: Device docker-thinpool is not a thin pool
  4. Thinkphp解决phpExcel导出数据量大导致内存溢出
  5. php curl post请求
  6. Java门面模式(思维导图)
  7. mysql 5.7.19安装
  8. TCP-HTTP ___UDP 应用场景
  9. 【坑】maven编码配置
  10. briup_JDBC