将经理更改为员工,使用 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')
那么基本上我的修改是否正确?还有
我需要写 e.lname 还是只写 lname,因为人们告诉我如果只有一项我可以简单地使用 lname?
当我使用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 名称或别名来限定列名 - 如果列是明确的,这是可选的,但通常在生产代码中限定是一个好习惯,因为:
- 您不必查阅方案来确定列所在的位置(自我记录)
- 如果架构发生变化,列不再明确,您的查询可能会突然中断,而您可能没有意识到原因
我的架构如下:
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')
那么基本上我的修改是否正确?还有
我需要写 e.lname 还是只写 lname,因为人们告诉我如果只有一项我可以简单地使用 lname?
当我使用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 名称或别名来限定列名 - 如果列是明确的,这是可选的,但通常在生产代码中限定是一个好习惯,因为:
- 您不必查阅方案来确定列所在的位置(自我记录)
- 如果架构发生变化,列不再明确,您的查询可能会突然中断,而您可能没有意识到原因