首页 > 解决方案 > 使用别名和子查询时要遵循哪些规则?

问题描述

看到这两个片段后我很困惑,一个有效,另一个无效。所以有一个MyTable有两列的表:IDValue

片段 1(失败)

/*Find the ID that is related to the maximum value*/
SELECT ID
FROM MyTable AS t /*Here MyTable can be a complex subquery. MyTable is just a placeholder here to show you can't use alias t in the subquery after WHERE*/
WHERE Value = (SELECT MAX(Value) FROM t) /*Get error here: 'Invalid object name t"*/

片段 2(工作)

/*Rank Value column*/
SELECT ID, Value,
(SELECT COUNT(Value) FROM MyTable WHERE Value >= t.Value) AS Rank /*No error raised here for t.Value*/
FROM MyTable AS t

这篇文章解释说

不能从同一范围内的子查询中引用别名

但什么是the same scope?它解释了为什么片段 2 有效吗?我假设还有其他可能的方法可以在不同的位置使用别名和子查询(例如在不同的子句中或以不同的方式嵌套)。那么在使用带有子查询的别名时,是否有任何通用的防错规则要遵循?

(请不要使用 CTE 等类似视图的技巧或 TOP 和 LIMIT 等变通方法)

标签: sqlsubqueryalias

解决方案


让我们看看第一个查询。

SELECT ID
FROM MyTable AS t
WHERE Value = (SELECT MAX(Value) FROM t)

这将尝试从表中选择别名t
这是不允许的。它应该从表或视图中选择。

例如:

SELECT ID
FROM MyTable AS t
WHERE Value = (SELECT MAX(Value) FROM MyTable)

请注意,这与范围无关。不使用任何子查询也是不允许的。

例如,这会因为同样的原因而失败

SELECT t1.*, t2.*
FROM MyTable AS t1
JOIN t1 AS t2 ON t2.id = t1.id

然后我们有第二个查询。

SELECT ID, Value,
( 
    SELECT COUNT(Value) 
    FROM MyTable t1sub
    WHERE t1sub.Value >= t1out.Value
) AS Rank
FROM MyTable AS t1out

这称为相关子查询。
该子查询通过 t1sub.Value 将外部查询的当前链接到t1out.Value子查询中的表。

它为外部查询中的每一行重新执行子查询。

关于范围。
它是关于 SQL 的一部分可以查看和使用的内容。

在前面的 SQL 中,t1sub别名只在相关子查询的范围内是已知的。
外部查询甚至不知道t1sub子查询中使用的别名。
在相关子查询中,t1out.Value可以看到和使用。

可以在db<>fiddle here上找到一些测试


推荐阅读