SQL相关子查询

时间:2017-09-17 13:50:33

标签: sql sql-server subquery

我对我不理解的相关子查询有疑问。 我知道外部表的每一行都运行一个相关的子查询。 例如:

Select departmentID, productid, unit_price
From products a
Where unit_price=(
Select MIN(unit_price)
 from products b
Where a.departmentID= b.departmentID
)
Order by a.departmentID

如果它为外部查询中的每一行运行,那么如果外部查询有3行,其中departmentID = 1,则子查询是否为departmentID = 1运行3次,即使它已经计算了MIN(unit_price)一次对于departmentID = 1?。

IMO对于departmentID = 1

多次运行子查询是愚蠢的

有人想详细说明吗?

编辑:第二个例子: 外:   选择departmentID,productid,unit_price     来自产品a     其中unit_price = 10且departmentID = 1 内:    SELECT MIN(unitprice)    来自Production.Products AS P2    在哪里P2.categoryid = 1

高于相关子查询的工作方式吗?

3 个答案:

答案 0 :(得分:3)

首先,如果您对数据库的工作方式有疑问,请使用您正在使用的数据库进行标记。

其次,您的查询是非敏感的,大多数数据库都会拒绝您的查询。您需要对子查询进行比较(例如=in)或exists

第三,这种说法不正确:

  

我知道外部表的每一行都会运行一个相关的子查询。

您应该知道的是,SQL是描述性语言,而不是过程语言。 SQL查询描述了您想要的输出。它不强制要求特定类型的处理。 SQL优化器确定了运行查询的最佳方法。

尽管如此,一些优化者比其他人更聪明。在某些数据库中,相关子查询将始终导致在外部查询中每行运行一次。 (甚至通过正确的索引也可以显着减轻这种行为。)这种行为不是语言的要求;这是这些数据库的限制。

答案 1 :(得分:0)

你误解了。 " ...相关子查询的语句为外表的每一行运行。"不应按字面意思理解。查询处理器,在任何数据库产品中智能地读取和处理优化的查询计划中的数据"在一个或多个抽象级别(比数据更接近)比在任何SQL语言中处理的基于集合的表示更低。 Google" Hash-Joins"," Merge Joins",或"查询优化"了解更多。

该语句仅指出子查询的结果将根据外部结果集的行中的数据而不同,因为它们依赖于该数据,而不相关的子查询,因为它不依赖于外部结果集中的行数据,所以对于每个外部行都是相同的。

答案 2 :(得分:0)

您的查询应该是 -

Select departmentID, productid, unit_price
From products a
Where unit_price = (  -- NOTE - 'unit_price = ' (the condition)
Select MIN(unit_price)
 from products b
Where a.departmentID= b.departmentID
)
Order by a.departmentID

如果表products包含departmentID = 1的多行,则会在departmentID = 1的每个时间运行子查询。这是程序性思维方式,在SQL的情况下是错误的,因为SQL是声明性语言。你不应该为每个记录迭代思考。

但请注意,之前的子查询结果不会存储在任何地方。

正如其他人所建议的那样,您不应该以这种方式考虑它,因为 查询规划器 会根据您的查询来处理获取结果的效率。

希望这有帮助。