思路:这题可以有三种解法。 第一二种类似,区别在于第一种方法是使用left join,第二种使用 inner join,其实区别并不大,酌情使用即可
-- 方法一:
select dp.dept_no, dp.dept_name, count(s.salary) as sum
from salaries s left join dept_emp d
on s.emp_no = d.emp_no
left join departments dp
on d.dept_no = dp.dept_no
group by dp.dept_no
order by dp.dept_no
-- 方法二:
select d.dept_no, d.dept_name, count(s.salary) as sum
from departments d join dept_emp de
on d.dept_no = de.dept_no
join salaries s
on de.emp_no = s.emp_no
group by d.dept_no
order by d.dept_no
大家可能会有疑问。为什么明明这里group by是对 dept_no 进行分组,但是select 子句后可以使用 dp.dept_name。 这是因为
当group by 后面跟上主键或者不为空唯一索引时,查询是有效的,因为此时的每一笔数据都具有唯一性。
我们可以从departments表中看出,每一个 dept_no 都是对应一个 dept_name 的,所以在select 子句后可以使用。但是在其他不是一一对应关系的情况下,这种查询是错误的
方法三:传统的按步骤来进行计算
思路:
- 查询每个员工在salaries表中的记录数:
select emp_no,count(emp_no) as counts from salaries group by emp_no
- 然后与dept_emp表连接,生成一个包含dept_no,emp_no,counts字段的临时表:
select de.dept_no,de.emp_no,en.counts
from dept_emp de
inner join (select emp_no,count(emp_no) as counts from salaries group by emp_no) as en
on de.emp_no = en.emp_no
- 最后将第二步生成的临时表再和departments进行连接,以dept_no分组,计算对于部门的所有员工的counts的总和,生成字段sum。最后进行order by排序
select d.dept_no, d.dept_name, sum(ds.counts)
from departments d join (
select de.dept_no, de.emp_no, en.counts
from
dept_emp de join (select emp_no, count(emp_no) as counts from salaries group by emp_no) as en
on de.emp_no = en.emp_no
) as ds
on d.dept_no = ds.dept_no
group by d.dept_no
order by d.dept_no