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

Left outer join vs subquery to include departments with no employees

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

问题如下:

列出所有部门名称和该部门的员工总数。员工总数列应重命名为 "total_emps"。从员工人数最少到员工人数最多的部门对列表进行排序。注意:您需要在列表中包含一个部门,即使该部门当前没有分配任何员工。

这是我的尝试:

SELECT Department.deptname

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

FROM Department

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

首先,它是左 outer 连接。现在,对于您的查询,您想加入基于 deptno 的 2 table,然后还按 deptno(或 deptname 分组,因为这很可能是unique) 以确保我们所做的任何聚合都是针对 table 中的每个唯一部门完成的。最后,使用 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 table 的位置来使用右外连接来完成同样的事情。

您尝试编写的查询是:
(table 从 's sqlfiddle to this 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。并且您遗漏了一个逗号。)

(系统要求您提供每个部门的名称和员工人数,所以这个 returns 那个。在实践中,如果 deptname 不是唯一的,我们可能会包括一个大概唯一的 deptno。)

I'm pretty sure my solution is not correct as it won't include departments with no employees.

即使是您的查询答案版本(添加了缺少的逗号)也有一个外部 select returns 每个部门的计数,无论子select returns。所以我不知道 why/how 你认为它不会。

如果您想使用 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;

(注意 LEFT JOIN 版本使用了更多概念:LEFT JOIN 扩展 NULL、GROUP BY 和 COUNT 的 NULL 行为用于非 *。)