选择没有经理的员工 - 两种解决方案

Select employees with no managers - two solutions

提问人:Csaba Benko 提问时间:11/15/2023 更新时间:11/15/2023 访问量:36

问:

我在一些测试平台上发现了以下测试任务。 我们有一个表定义:

CREATE TABLE employees
(
    id integer NOT NULL,
    name character varying(20),
    "managerId" integer,
    CONSTRAINT employees_pkey PRIMARY KEY (id)
)

如果任何其他员工设置了此 eomployee 的 ID,则该员工是经理。卡罗尔是一名经理,如果至少在其他员工身上有他们的设置卡罗尔。managerIdmanagerIdid

编写一个查询,选择非经理员工的姓名。

为此,我提出了 2 种可能的解决方案:

解决方案 1:

select e.name
from public.employees as e
where not exists (select e1."managerId" from public.employees as e1 where e1."managerId" = e.id);

解决方案 2:

select e.name
from employees as e 
left outer join public.employees as e1 on e.id = e1."managerId"
group by e.name
having count(e1.id) = 0;

运行一些自动测试来验证代码是否正确。

我的第一个解决方案通过了验证,但我的第二个解决方案失败了。消息只说:“工人有经理:错误的答案”。当然,我不知道那个测试的内容。我试图提出不同的测试场景,上面两个解决方案带来了不同的结果,但无法想出一个。

对于为我的两个解决方案带来不同结果的测试数据,您有什么建议吗?我真的很想知道我的第二个解决方案在哪里失败了。

谢谢你的帮助。

SQL SELECT 条件语句 筛选

评论


答:

0赞 seanb 11/15/2023 #1

第二个可能是不正确的(尽管在实践中不太可能)。

  • 如果两个人的名字相同,一个是经理,另一个不是,那么 GROUP BY 会合并这些名称并将他们视为经理,因为它仅按“名称”分组

例如,如果您的数据如下所示,则第二种解决方案将找不到任何非经理。

id          name                 managerId
----------- -------------------- -----------
1           Spartacus            NULL
2           Spartacus            1

选项

  • 人们经常使用您在第二个答案中的方法,但不是分组,而是使用第二个表中的 IS NULL(这意味着您不需要处理“GROUP BY”,您只需找到空白)。 例如,
select e.name
from employees as e 
left outer join public.employees as e1 on e.id = e1."managerId"
where e1.id IS NULL
  • 另一种方法是确保分组包含主键 - 确保原始表中的每一行都得到唯一处理,例如,
select e.id, e.name
from employees as e 
left outer join public.employees as e1 on e.id = e1."managerId"
group by e.id, e.name
having count(e1.id) = 0;

要使自动测试结果通过,您需要确保只选择了名称(而不是 ID)。根据所使用的 SQL 产品,您可能只选择名称;或者,您需要将上述内容转换为 CTE 或子查询,然后从中选择名称。

注意:在第二个解决方案中,您错过了其中一个表。public.