【问题标题】:sql for all departments count employees who do not work on a project for that department所有部门的 sql 计算不参与该部门项目的员工
【发布时间】:2018-03-26 12:39:22
【问题描述】:

我需要创建一个视图来报告部门名称以及有多少员工没有参与该部门控制的任何项目。

我知道如何创建视图,并且还想出了方法来计算有多少员工通过联接为部门的项目工作,但不知道如何获得不这样做的员工数量,与那个部门配对。这是通用 SQL,与特定 DBMS 无关,因此我可能需要避免仅限于特定 DBMS 的晦涩 SQL 命令。

我已经创建了我认为与这里的问题相关的架构部分的模型:

Create Table DEPARTMENT (Dname VARCHAR(30), Dnumber INTEGER primary key , Mgr_ssn INTEGER, Mgr_start_date Varchar(30));
INSERT INTO Department (Dname,Mgr_ssn,Mgr_start_date) values ('maths',1,'foo');
INSERT INTO Department (Dname,Mgr_ssn,Mgr_start_date) values ('physics',2,'foo');


Create Table PROJECT (Pname VARCHAR(30), Pnumber INTEGER primary key , Plocation varchar(10), Dnum INTEGER);
INSERT INTO PROJECT (Pname,Plocation,Dnum) values ('project','the moon',1);
INSERT INTO PROJECT (Pname,Plocation,Dnum) values ('project','the moon',1);
INSERT INTO PROJECT (Pname,Plocation,Dnum) values ('project','the moon',2);
INSERT INTO PROJECT (Pname,Plocation,Dnum) values ('project','the moon',2);
INSERT INTO PROJECT (Pname,Plocation,Dnum) values ('project','the moon',2);

Create Table EMPLOYEE (Fname VARCHAR(30), SSn INTEGER primary key);
INSERT INTO EMPLOYEE (Fname) VALUES ('rick');
INSERT INTO EMPLOYEE (Fname) VALUES ('rick');
INSERT INTO EMPLOYEE (Fname) VALUES ('rick');
INSERT INTO EMPLOYEE (Fname) VALUES ('rick');
INSERT INTO EMPLOYEE (Fname) VALUES ('rick');

Create Table WORKS_ON (Essn INTEGER,Pno INTEGER, primary key(Essn,Pno));
INSERT INTO WORKS_ON VALUES(1,1);
INSERT INTO WORKS_ON VALUES(2,4);
INSERT INTO WORKS_ON VALUES(3,3);
INSERT INTO WORKS_ON VALUES(4,4);
INSERT INTO WORKS_ON VALUES(4,3);
INSERT INTO WORKS_ON VALUES(4,2);

虽然这是一项学术练习,但这不是一项作业,因此,如果我没有完成这项工作,或者无法获得解决方案的帮助,我将永远不知道如何处理这些类型的查询。

我尝试的第一件事是计算每个现有员工的数量,然后尝试减去每个部门从事项目工作的每个员工的数量,但我无法计算出所有的行。我一直无法使用 SET Minus 和子查询获得其他解决方案。

编辑:我必须获得每个部门从事项目的员工人数:

SELECT Dnumber, count(*) num_employees_on_projects FROM department d
INNER JOIN PROJECT p on d.Dnumber = p.Dnum
INNER JOIN WORKS_ON w on w.Pno = p.Pnumber 
INNER JOIN EMPLOYEE e on e.Ssn = w.essn
group by Dnumber

【问题讨论】:

  • 您是否尝试过使用“NOT”关键字?
  • 要符合 ANSI SQL 和可移植性,您需要为主键定义默认值,或显式插入它们的值。
  • 不能这么简单地使用 NOT 关键字,因为通过将部门加入 project 和works_on 来获取员工数量,以获取包含部门编号和员工 ssn 的记录列表。
  • 至少你的 mock up 应该是有效的 SQL,目前那些插入会失败。
  • @dnoeth 我将 sqlfiddle 设置为 sqlite(从不允许视图中的子查询的 mySQL 5.7 更改),其中整数主键自动设置和递增。向这些插入添加 AUTO_INCREMENT 在 mySQL 中也可以正常工作。

标签: sql select subquery


【解决方案1】:

您需要切换到外连接以包含不匹配的行。然后从最右边的表 (WORKS_ON) 中计算一个已知为 NOT NULL 的列,最简单的是连接列:

SELECT Dnumber,
   count(*) as all_employees,
   count(w.Pno) as employees_on_projects,
   count(*) - count(w.Pno) as employees_without_project
FROM department d
LEFT JOIN PROJECT p on d.Dnumber = p.Dnum
LEFT JOIN WORKS_ON w on w.Pno = p.Pnumber 
-- LEFT JOIN EMPLOYEE e on e.Ssn = w.essn -- not needed
group by Dnumber;

编辑:

要将每个部门的数据与员工总数相关联,您可以添加一个标量子查询:

SELECT Dnumber,
   count(w.Pno) as employees_on_projects,
   (SELECT count(*) FROM EMPLOYEE) -- all employees
    - count(w.Pno) as employees_without_project
FROM department d
LEFT JOIN PROJECT p on d.Dnumber = p.Dnum
LEFT JOIN WORKS_ON w on w.Pno = p.Pnumber 
group by Dnumber;

fiddle

【讨论】:

  • 非常感谢您的回答,这实际上让我对另一种解释问题的方式以及我将如何实现这一点有了一个看法。但是,我最初的目标是从全球员工总数中减去一个项目的员工数量,仍然无法计算出来。
  • 由于某种原因,当我添加另一个部门时,我得到了这些结果,而我预计有 0 名员工和 6 名员工不在项目中sqlfiddle.com/#!7/f59332/2
  • @tavtavtav:你的预期结果是什么?
  • 因为总共有 6 名员工,那么那些有 4 人在为该部门工作的部门应该返回数字 2。
  • @tavtavtav:现在我明白了。当您想要获取每个部门的数据时,最简单的方法是添加一个返回员工人数的标量子查询。我会修改我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-09
  • 2022-12-19
  • 1970-01-01
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多