将经理更改为员工,使用 not in 子句,在使用联合命令时有些混乱

changing manager to employee, using not in clause, some minor confusing in using joint commands

我的架构如下:

EMPLOYEE (fmane, minit, lname, ssn, birthdate, address, sex, salary, superssn, dno), KEY: ssn
DEPARTMENT (dname, dnumber, mgrssn, mgrstartdate), KEY: dnumber.
PROJECT  (pname, pnumber, plocation, dnum), KEY: pnumber.
WORKS_ON (essn, pno, hours), KEY: (essn, pno)
DEPENDENT  (essn, dependent-name, sex, bdate, relationship), KEY: (essn, dependent-name)

我想找到那些不在芝加哥从事任何项目的经理的姓氏和 SSN。

注:我修改了原题在SQL上练习,所以我把managers改成了employees

这是我目前的情况:

  select e.lname
  from Employee e
  where e.ssn not in 
       (select w.essn
        from works_on w, Project p
        where w.pno = p.pnumber
        and p.plocation = 'Cleveland')

那么基本上我的修改是否正确?还有

  1. 我需要写 e.lname 还是只写 lname,因为人们告诉我如果只有一项我可以简单地使用 lname?

  2. 当我使用NOT IN子句时最令人困惑的部分,我怎么知道什么时候应该使用e.ssn或ssn?

谢谢

使用 not in (...) 可以说是最容易 read/understand,但通常效果最差。

性能最好的通常是对丢失的连接进行外部连接过滤:

select ssn, lname
from Employee e
left join (
    select essn
    from Project p
    join works_on w on pno = pnumber
    where plocation = 'Cleveland') x on essn = ssn
where essn is null

这与以下结果相同:

select ssn, lname
from Employee e
where ssn not in (
    select essn
    from Project p
    join works_on w on pno = pnumber
    where plocation = 'Cleveland')

请注意,在这两种方法中,子查询 select 首先来自 Project 并使用 where 子句到 select 克利夫兰位置,这为优化器提供了最佳有机会在位置上使用索引(如果存在),and/or 做最少的工作来让在其中工作的员工(通过 pno 上的索引,如果存在)。

还要注意正确连接的使用(其语法在 20 多年前成为 SQL 标准的一部分)。


关于使用 table 名称或别名来限定列名 - 如果列是明确的,这是可选的,但通常在生产代码中限定是一个好习惯,因为:

  • 您不必查阅方案来确定列所在的位置(自我记录)
  • 如果架构发生变化,列不再明确,您的查询可能会突然中断,而您可能没有意识到原因