提问人:Csaba Benko 提问时间:11/15/2023 更新时间:11/15/2023 访问量:36
选择没有经理的员工 - 两种解决方案
Select employees with no managers - two solutions
问:
我在一些测试平台上发现了以下测试任务。 我们有一个表定义:
CREATE TABLE employees
(
id integer NOT NULL,
name character varying(20),
"managerId" integer,
CONSTRAINT employees_pkey PRIMARY KEY (id)
)
如果任何其他员工设置了此 eomployee 的 ID,则该员工是经理。卡罗尔是一名经理,如果至少在其他员工身上有他们的设置卡罗尔。managerId
managerId
id
编写一个查询,仅选择非经理员工的姓名。
为此,我提出了 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;
运行一些自动测试来验证代码是否正确。
我的第一个解决方案通过了验证,但我的第二个解决方案失败了。消息只说:“工人有经理:错误的答案”。当然,我不知道那个测试的内容。我试图提出不同的测试场景,上面两个解决方案带来了不同的结果,但无法想出一个。
对于为我的两个解决方案带来不同结果的测试数据,您有什么建议吗?我真的很想知道我的第二个解决方案在哪里失败了。
谢谢你的帮助。
答:
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.
下一个:SQL 按行减去成本
评论