用来表示部门信息的表,通过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)
用来表示雇员信息的表,与其他表通过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)
表示正在进行的项目的表,在此问题中通过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表中一个人进行了多个项目。这时,一个人的工作时长得多次记录,但是工资却不行。
一次查询的思路大概行不通。
我们可以先查找一个包含各部门总工资的临时表,这个查询只需要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)
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)
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