非相关和相关嵌套语句之间有什么区别?

时间:2013-04-28 02:55:11

标签: sql sql-server

我对非相关和相关嵌套选择语句之间的区别感到困惑?我是一名学生,我正在尝试创建一个相关的声明,但我不确定我是否正确地做了。

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。当子查询跟随=,!=,&lt;,&lt; =,&gt;,&gt; =或子查询用作表达式时,不允许这样做。”< / p>

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

1 个答案:

答案 0 :(得分: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)。由于显而易见的原因,独立子查询只需逻辑执行一次。