【问题标题】:Is there any advantages of using nested queries when not necessary in Oracle SQL?在 Oracle SQL 中不需要时使用嵌套查询有什么好处吗?
【发布时间】:2021-03-29 20:55:47
【问题描述】:

我有一个表 EMPLOYEE,其中包含以下属性:Name、Ssn、Super_Ssn 其中 Super_Ssn 是主管的 ssn,我要编写以下查询:

检索其上司的上司拥有的所有员工的姓名 “888665555”代表 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’

我的问题如下:

  • 如果我有类似的查询,我有什么理由应该诉诸他们给定的方法吗?
  • 在不需要时使用嵌套查询有什么好处吗?

【问题讨论】:

  • 您自己的解决方案的实际问题 是您使用的是已弃用(而且很糟糕)的旧式 JOIN 语法。您应该使用现代(嗯,“现代”意思是 30 岁)显式 JOIN 语法。 stackoverflow.com/questions/128965/…
  • 1) 它们不等价 2) 旧语法。使用JOIN 时,由于 1:m 关系(取决于数据),您可能会得到重复
  • @Dai 我学习了不同类型的连接,但我发现这是最容易编写的,这就是我使用它的原因,感谢您分享该链接
  • @LukaszSzozda 你能指出我自己的解决方案有什么问题吗?
  • @Sergio 我并不是说这是错误的。我指出JOININ 可能会导致不同的结果。一般来说,它们是不等价的。请准备样本数据dbfiddle.uk

标签: sql oracle join subquery


【解决方案1】:

在这个查询中:

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 子句中使用,以便将表的所有Super_ssns 与其值进行比较。
所以给定的解决方案是一个相当简单易读的查询。

您的查询存在缺陷。
您对连接使用过时的语法,并且您正在执行 2 个连接,尽管只需要 1 个。
你可以这样写你的查询:

SELECT e.Name
FROM EMPLOYEE e INNER JOIN EMPLOYEE s
ON s.Ssn = e.Super_ssn
WHERE s.Super_ssn = '888665555'

如果您知道连接的工作原理,这也是一个简单的查询和可读性。

【讨论】:

  • 哦,我刚注意到(抱歉不熟悉内部连接),谢谢!
  • @Dai 如果子查询 嵌套 在另一个子查询中,我认为它是嵌套的。如果不是,那么它只是一个子查询。
  • 如果我使用“嵌套子查询”定义“嵌套子查询”,那将是 tautological。我使用英文单词“nested”定义了“nested subquery”。这是两种不同的东西。
  • @forpas 可能会显得争论不休,我会说我觉得这个定义一点用都没有,因为你说... WHERE Super_ssn IN ( SELECT SSN FROM ...) SELECT SSN FROM EMPLOYEE 部分不是嵌套子查询[1] ,但使用简单的英语语言定义,它是“嵌套”查询,因为它是嵌套在 WHERE 中的 SELECT,嵌套在 SELECT 中。 [1] 您写道“没有嵌套的子查询,因为 [..] 没有嵌套在另一个子查询中。” - 在另一个 SELECT 中有一个 SELECT 怎么不是“嵌套”(在英语的意义上)?
  • 我很惊讶地在Oracle 19c SQL Reference 中发现:SELECT 语句的WHERE 子句中的子查询也称为嵌套子查询 .在嵌套子查询中最多可以嵌套 255 级子查询。 我通常假设 嵌套子查询 意味着它在另一个子查询中。如果您可以将任何子查询称为嵌套子查询,那么该术语将毫无意义,或者至少是重言式的。 嵌套查询不是 Oracle 使用的术语。
【解决方案2】:

您的查询不会运行,因为您没有指定从哪个 employee 获取 name。从逻辑上讲,唯一不同的是您可能会得到重复的行,例如s 中可能有一些行具有相同的ssnsupervisor_ssn,尽管ssn 似乎是一个唯一键,所以这不会发生。使用这种连接方式没有任何问题。

Oracle 能够很好地优化这两个查询,因此您不必担心大部分情况 - 只要您不依赖 in (subquery) 的半联接特性。

其他 RDBMS 的转换可能不那么聪明,因此您可能会发现第一个查询会强制执行某些执行计划(这可能是可取的,也可能不是可取的),但第二个查询将为优化器提供更大的灵活性。

【讨论】:

  • 是 ssn 是主键,我的 WHERE 子句怎么不指定选择哪个员工的姓名?\
  • 不是你的 where 子句,而是你的 select 子句。它只是说select name。尝试自己运行它并查看错误
猜你喜欢
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多