MySQL:查询每个部门的员工小时平均工资(显示部门名称、部门员工小时平均 工资)

这里写自定义目录标题

  • 介绍
    • 涉及的表的结构
      • table department
      • table employee
      • table works_on
    • 思路
  • 建立大表(三表联合)一次查询
  • 临时表多次查询
  • 总结

介绍

涉及的表的结构

table department

用来表示部门信息的表,通过dno字段与其他表关联

mysql> select * from department;
+---------------------------+-----+--------+--------------+
| dname                     | dno | mgrssn | mgrstartdata |
+---------------------------+-----+--------+--------------+
| Economy Department        | 000 | 09     | 2020-03-01   |
| Sales Department          | 001 | 06     | 2017-06-01   |
| Human Resource Department | 010 | 12     | 2003-12-01   |
| Produce Department        | 011 | 14     | 2009-05-01   |
| Research Department       | 100 | 20     | 2026-09-01   |
+---------------------------+-----+--------+--------------+
5 rows in set (0.05 sec)

table employee

用来表示雇员信息的表,与其他表通过dno字段关联

mysql> select * from employee;
+--------+------+----------------------------------+---------+----------+-----+
| ename  | essn | address                          | salary  | superssn | dno |
+--------+------+----------------------------------+---------+----------+-----+
| 白玉芬 | 00   | 广州市天河区珠江新城花城大道83| 1000.00 | 24       | 100 |
| 仓春莲 | 01   | 广东省广州市石牌西路68| 1100.00 | 20       | 100 |
| 仓红   | 02   | 广州市番禺区市桥清河东路41| 1500.00 | 14       | 011 |
| 陈超云 | 03   | 佛山市汾江西路13| 3000.00 | 02       | 011 |
| 陈高   | 04   | 佛山市南海区桂城天佑三路1号大院  | 4000.00 | 06       | 001 |
| 陈国祥 | 05   | 佛山市顺德区容奇大道东23| 3500.00 | 09       | 000 |
......
+--------+------+----------------------------------+---------+----------+-----+
61 rows in set (0.34 sec)

table works_on

表示正在进行的项目的表,在此问题中通过dno与dapartment表相连

mysql> select * from works_on;
+------+-----+-------+
| essn | pno | hours |
+------+-----+-------+
| 00   | P1  |     8 |
| 01   | P2  |     3 |
| 02   | P4  |     4 |
| 03   | P1  |     1 |
| 03   | P3  |     2 |
| 03   | P5  |     1 |
......
+------+-----+-------+
111 rows in set (19.70 sec)

思路

需要计算各部门的平均小时工资,就必须计算各部门的总工作时长和总工资。工作时长按照个人/项目/时长的样式存储在works_on表中,工资以个人/部门编号/工资的样式储存在employee表中,并且查询还需要显示部门名称。所以整个查询至少需要三表的联合查询,但怎样联合,有以下不同的思路。

建立大表(三表联合)一次查询

从速度优先的角度考虑,自然建立包含所有信息的大表查询最优先。

+---------------------------+-----+--------+--------------+--------+------+----------------------------------+---------+----------+-----+------+-----+-------+
| dname                     | dno | mgrssn | mgrstartdata | ename  | essn | address                          | salary  | superssn | dno | essn | pno | hours |
+---------------------------+-----+--------+--------------+--------+------+----------------------------------+---------+----------+-----+------+-----+-------+
| Research Department       | 100 | 20     | 2026-09-01   | 白玉芬 | 00   | 广州市天河区珠江新城花城大道83| 1000.00 | 24       | 100 | 00   | P1  |     8 |
| Research Department       | 100 | 20     | 2026-09-01   | 仓春莲 | 01   | 广东省广州市石牌西路68| 1100.00 | 20       | 100 | 01   | P2  |     3 |
| Produce Department        | 011 | 14     | 2009-05-01   | 仓红   | 02   | 广州市番禺区市桥清河东路41| 1500.00 | 14       | 011 | 02   | P4  |     4 |
| Produce Department        | 011 | 14     | 2009-05-01   | 陈超云 | 03   | 佛山市汾江西路13| 3000.00 | 02       | 011 | 03   | P1  |     1 |
| Produce Department        | 011 | 14     | 2009-05-01   | 陈超云 | 03   | 佛山市汾江西路13| 3000.00 | 02       | 011 | 03   | P3  |     2 |
......
+---------------------------+-----+--------+--------------+--------+------+----------------------------------+---------+----------+-----+------+-----+-------+
111 rows in set (0.46 sec)

然后我们在这张表上用group by划分来计算各个部门的总工资和总工时。所以我们直接查询

mysql> SELECT department.dno,SUM(works_on.hours),SUM(employee.salary)
    -> from (department JOIN employee ON department.dno = employee.dno)
 JOIN works_on ON works_on.essn = employee.essn
    -> GROUP BY department.dno;
+-----+---------------------+----------------------+
| dno | SUM(works_on.hours) | SUM(employee.salary) |
+-----+---------------------+----------------------+
| 000 | 52                  | 54900.00             |
| 001 | 58                  | 90200.00             |
| 010 | 42                  | 38900.00             |
| 011 | 121                 | 132600.00            |
| 100 | 125                 | 117800.00            |
+-----+---------------------+----------------------+
5 rows in set (0.08 sec)

这样可以么?
通过观察三联大表发现,同一个人可能出现多次。这是由于等值连接时,works_on表中一个人进行了多个项目。这时,一个人的工作时长得多次记录,但是工资却不行。

一次查询的思路大概行不通。

临时表多次查询

  1. 查询总工资

我们可以先查找一个包含各部门总工资的临时表,这个查询只需要employee一张表就可以实现:

mysql> select dno, SUM(employee.salary)
    from employee
    group by employee.dno;
+-----+----------------------+
| dno | SUM(employee.salary) |
+-----+----------------------+
| 000 | 31500.00             |
| 001 | 38600.00             |
| 010 | 29200.00             |
| 011 | 92000.00             |
| 100 | 59600.00             |
+-----+----------------------+
5 rows in set (0.12 sec)
  1. 查询总工时
    然后查询一张包含各部门总工时的临时表,这个查询需要works_on和employee联合才可以实现
select dno, SUM(works_on.hours)
    from works_on join employee on works_on.essn = employee.essn
    group by employee.dno;
+-----+---------------------+
| dno | SUM(works_on.hours) |
+-----+---------------------+
| 000 | 52                  |
| 001 | 58                  |
| 010 | 42                  |
| 011 | 121                 |
| 100 | 125                 |
+-----+---------------------+
5 rows in set (0.08 sec)
  1. 联合两表计算平均工资
mysql> SELECT s_Hours.dno, s_Salary.s_s/s_Hours.s_h
FROM (
	(SELECT employee.dno,SUM(works_on.hours) as s_h
	FROM employee JOIN works_on ON works_on.essn = employee.essn
	GROUP BY employee.dno) s_Hours
	JOIN
	(SELECT employee.dno,SUM(employee.salary) as s_s
	FROM employee JOIN department ON employee.dno = department.dno
	GROUP BY employee.dno) s_Salary
	ON s_Salary.dno = s_Hours.dno
);
+-----+--------------------------+
| dno | s_Salary.s_s/s_Hours.s_h |
+-----+--------------------------+
| 000 | 605.769231               |
| 001 | 665.517241               |
| 010 | 695.238095               |
| 011 | 760.330579               |
| 100 | 476.800000               |
+-----+--------------------------+
5 rows in set (0.11 sec)

总结

这个题目的重点在于对临时表的应用以及用group对组别的划分。

临时表在后面还需要使用查询时必须进行临时命名。
同时一些临时列也需要进行命名才可以select

你可能感兴趣的:(数据库课程,mysql)