0

我对非相关和相关嵌套选择语句之间的区别感到困惑?我是一名学生,我正在努力创建一个相关的陈述,但我不确定我是否做得正确。

SELECT P.Firstname  AS First, 
   P.Lastname   AS Last, 
   AVG(C.grade) AS Cgpa
FROM   Person P, 
       Class C 
WHERE  P.stdNo = (SELECT S.stdNo
    FROM   School S
    WHERE  S.No = C.No)
    GROUP BY P.LastName , P.FirstName
    ORDER BY P.LastName

这目前不起作用。我收到此错误“子查询返回超过 1 个值。当子查询遵循 =、!=、<、<=、>、>= 或将子查询用作表达式时,这是不允许的。”

编辑代码:这是一个相关的选择语句吗?

4

1 回答 1

1

首先,让我们处理您的特定问题。使用子查询时,必须注意其上下文。有两种上下文:表和标量。在表上下文中,子查询应返回一组行。在标量上下文中,它需要返回单个值(一行一列)。你怎么知道哪个是哪个?表上下文将由以下结构指示:

FROM (...)
JOIN (...)
WHERE ... IN(...)

标量上下文或多或少在其他任何地方。如果您将子查询的结果与单个值(如 where 子句中的列)进行比较,或者将结果用作 SELECT 字段列表中的计算列,则子查询处于标量上下文中。

在您的特定查询中,您将子查询的结果与 NULL 进行比较。由于 NULL 是单个值,因此我们讨论的是标量上下文。因此,子查询需要返回单个结果。你的不是,它可能正在发生,因为一个人所属的学校有很多。不管。我想我能猜出你打算做什么。您只想包括属于至少一所学校的人员。您可以像这样更有效地编写它:

WHERE EXISTS(SELECT * FROM School S WHERE P.stdNo = S.stdNo)

您可以将 替换*为列或表达式。这并不重要,因为EXISTS()测试是否返回任何行并且不对特定结果做任何事情。

但是,您有一个更大的问题,那就是您正在对 Person 和 Class 表进行笛卡尔积。我假设您实际上希望以某种方式将人们与课程相匹配。因为使用逗号运算符很容易意外地进行笛卡尔连接,所以我总是使用并推荐显式JOIN运算符。如果你说INNER JOIN(或其他类型)而不指定连接谓词,你会得到一个语法错误。所以你应该有这样的东西:

FROM Person P
JOIN Class C
  ON <condition>

现在,对于您关于独立子查询与相关子查询的其他问题。一个独立的子查询是最简单的情况。这是一个子查询,它不引用查询中在其外部使用的任何表或列。相关子查询引用在其外部使用的表或列。您的子查询是相关的,因为它引用了P.stdNo,它包含在子查询之外的查询中。相关子查询必须对其包含的上下文中的每一行进行逻辑执行。在您的情况下,WHERE 子句检查的每一行都会导致子查询的逻辑执行,使用来自该特定行的数据(在这种情况下,P.stdNo)。出于显而易见的原因,独立子查询只需要在逻辑上执行一次。

于 2013-04-28T03:12:40.107 回答