左外连接与子查询,包括没有员工的部门

时间:2015-01-20 11:57:06

标签: mysql sql subquery left-join scalar-subquery

假设我有以下数据库模型:

enter image description here

问题如下:

列出所有部门名称和部门中的员工总数。员工总数列应重命名为“total_emps”。从具有最少员工的部门到最多员工的部门订购列表。注意:即使部门当前没有分配任何员工,您也需要在列表中包含一个部门。

这是我的尝试:

SELECT Department.deptname

   (SELECT COUNT(*)
   FROM Department
   WHERE Department.empno = Employee.empno ) AS total_emps

FROM Department

我很确定我的解决方案不正确,因为它不包括没有员工的部门。你如何使用左内连接来解决这个问题?

2 个答案:

答案 0 :(得分:1)

首先,它是左外部加入。现在,对于您的查询,您希望根据deptno加入2个表,然后按deptno(或deptname分组,因为这可能是唯一的)以确保我们所做的任何聚合都是针对表中的每个唯一部门完成的。最后,使用count函数完成计数,从而导致此查询:

select d.deptname, count(e.empno) as total_emps
from department d 
left join employee e on d.deptno = e.deptno
group by d.deptname

SQLFiddle

请注意,由于我们需要department中的所有记录,无论employee中是否有匹配的记录,department必须出现在联接的左侧。通过交换连接中2个表的位置,我们可以使用右外连接完成相同的操作。

答案 1 :(得分:1)

您尝试编写的查询是:
(表格从shree.pat18的sqlfiddle修改为此sqlfiddle

create table department (deptno int, deptname varchar(20));
insert into department values (1, 'a'),(2, 'b'),(3, 'c');
create table employee (empno int, deptno int);
insert into employee values (1,1),(2,1),(3,3);

SELECT d.deptname, 
    (SELECT COUNT(*)
    FROM EMPLOYEE e
    WHERE d.deptno = e.deptno ) AS total_emps
FROM DEPARTMENT d
ORDER BY total_emps ASC;

(您从DEPARTMENT开始计算,而不是EMPLOYEE并比较empno而不是deptno。并且您省略了逗号。)

(系统会要求您提供每个部门的姓名和员工人数,以便将其返回。实际上,如果deptno不是唯一的话,我们会包含一个大概是唯一的deptname。)

  

我很确定我的解决方案不正确,因为它不会包括在内   没有雇员的部门。

即使您的答案的查询版本(添加了缺少的逗号)也有一个外部选择,无论子选择返回什么,都会返回每个部门的计数。所以我不知道为什么/你认为它不会如何。

如果要使用LEFT(OUTER)JOIN,那么没有员工的DEPARTMENT行会被NULL扩展。但是列的COUNT只计算非NULL行。

SELECT d.deptname, COUNT(e.empno) AS total_emps
FROM DEPARTMENT d
LEFT JOIN EMPLOYEE e
ON d.deptno = e.deptno
GROUP BY d.deptno
ORDER BY total_emps ASC;

(Nb LEFT JOIN版本使用更多概念:LEFT JOIN扩展为NULL,GROUP BY和COUNT&non-*的NULL行为。)