在 Oracle SQL 中不需要时使用嵌套查询有什么好处吗?
Is there any advantages of using nested queries when not necessary in Oracle SQL?
我有一个 table EMPLOYEE 并且其中有以下属性:Name, Ssn, Super_Ssn 其中 Super_Ssn 是主管的 ssn,我要写以下查询:
Retrieve the names of all employees whose supervisor’s supervisor has
‘888665555’ for Ssn.
给出的解决方案:
SELECT
Name
FROM
EMPLOYEE
WHERE
Super_ssn IN ( SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN=‘888665555’ )
虽然我写了以下内容:
SELECT
Name
FROM
EMPLOYEE E,
EMPLOYEE S,
EMPLOYEE SS
WHERE
E.Super_ssn = S.Ssn
AND
S.Super_ssn = SS.Ssn
AND
ss.Ssn=‘888665555’
我的问题如下:
- 如果我有类似的查询,我有什么理由应该使用他们给定的方法吗?
- 在不需要时使用嵌套查询有什么好处吗?
在此查询中:
SELECT Name
FROM EMPLOYEE
WHERE Super_ssn IN (SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN = '888665555')
没有嵌套子查询,因为:
SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN = '888665555'
没有嵌套在另一个里面。
它也不是相关的子查询,所以我希望它只执行一次并且它的结果集将在 WHERE
子句中使用,以便比较 table 的所有 Super_ssn
s反对它的价值观。
所以给定的解决方案是一个相当简单可读的查询。
您的查询有缺陷。
您对联接使用了过时的语法,并且您正在进行 2 次联接,尽管只需要 1 次。
您可以像这样编写查询:
SELECT e.Name
FROM EMPLOYEE e INNER JOIN EMPLOYEE s
ON s.Ssn = e.Super_ssn
WHERE s.Super_ssn = '888665555'
如果您知道联接的工作原理,这也是一个简单的查询并且可读。
您的查询不会 运行 因为您没有指定要从哪个 employee
中获取 name
。从逻辑上讲,will 唯一不同的是您可能会得到重复的行,例如 s
中可能有一些行具有相同的 ssn
和 supervisor_ssn
,尽管 ssn
是唯一键,因此不会发生这种情况。使用这种连接方式没有任何问题。
Oracle 能够很好地优化这两个查询,因此您在大多数情况下不必担心 - 只要您不依赖 in (subquery)
的半连接性质。
其他 RDBMS 的转换可能不那么聪明,因此您可能会发现第一个查询强制执行某些执行计划(这可能是合意的,也可能不是合意的),但第二个查询将为优化器提供更大的灵活性。
我有一个 table EMPLOYEE 并且其中有以下属性:Name, Ssn, Super_Ssn 其中 Super_Ssn 是主管的 ssn,我要写以下查询:
Retrieve the names of all employees whose supervisor’s supervisor has ‘888665555’ for Ssn.
给出的解决方案:
SELECT
Name
FROM
EMPLOYEE
WHERE
Super_ssn IN ( SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN=‘888665555’ )
虽然我写了以下内容:
SELECT
Name
FROM
EMPLOYEE E,
EMPLOYEE S,
EMPLOYEE SS
WHERE
E.Super_ssn = S.Ssn
AND
S.Super_ssn = SS.Ssn
AND
ss.Ssn=‘888665555’
我的问题如下:
- 如果我有类似的查询,我有什么理由应该使用他们给定的方法吗?
- 在不需要时使用嵌套查询有什么好处吗?
在此查询中:
SELECT Name
FROM EMPLOYEE
WHERE Super_ssn IN (SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN = '888665555')
没有嵌套子查询,因为:
SELECT SSN FROM EMPLOYEE WHERE SUPER_SSN = '888665555'
没有嵌套在另一个里面。
它也不是相关的子查询,所以我希望它只执行一次并且它的结果集将在 WHERE
子句中使用,以便比较 table 的所有 Super_ssn
s反对它的价值观。
所以给定的解决方案是一个相当简单可读的查询。
您的查询有缺陷。
您对联接使用了过时的语法,并且您正在进行 2 次联接,尽管只需要 1 次。
您可以像这样编写查询:
SELECT e.Name
FROM EMPLOYEE e INNER JOIN EMPLOYEE s
ON s.Ssn = e.Super_ssn
WHERE s.Super_ssn = '888665555'
如果您知道联接的工作原理,这也是一个简单的查询并且可读。
您的查询不会 运行 因为您没有指定要从哪个 employee
中获取 name
。从逻辑上讲,will 唯一不同的是您可能会得到重复的行,例如 s
中可能有一些行具有相同的 ssn
和 supervisor_ssn
,尽管 ssn
是唯一键,因此不会发生这种情况。使用这种连接方式没有任何问题。
Oracle 能够很好地优化这两个查询,因此您在大多数情况下不必担心 - 只要您不依赖 in (subquery)
的半连接性质。
其他 RDBMS 的转换可能不那么聪明,因此您可能会发现第一个查询强制执行某些执行计划(这可能是合意的,也可能不是合意的),但第二个查询将为优化器提供更大的灵活性。