声称子查询只能返回单个列
Posted
技术标签:
【中文标题】声称子查询只能返回单个列【英文标题】:The claim that subqueries can only return single columns 【发布时间】:2017-01-30 00:35:42 【问题描述】:我正在阅读 Ben Fortas “在 10 分钟内自学 SQL”一书,它有灰色框警告:“子查询 SELECT 语句只能检索单个列。尝试返回多个列将返回错误。”
事实上,对于 RDMS 来说,这通常是正确的吗? (请注意,如果this answer 正确,则并非所有数据库都正确)。
为什么它会是真的?这似乎是一个奇怪的语言限制。查询的计算成本很高,检索 3 列的工作与检索 1 的工作在计算上并没有特别的不同(除非您的 RDMS 存储按列分组而不是按行分组的表)。
【问题讨论】:
在 SELECT 字段或非集合比较(如=
、<
等...)中使用子查询结果时一般不成立except。
是关于SELECT
子句中的子查询吗?
从您的描述来看,他似乎在谈论列定义中的子查询,而不是在您发布的链接中作为 FROM 语句中的派生表的子选择/查询。一列不能容纳多列。并且 Column 不能容纳多行,因此在列定义中使用时它必须是单个标量结果。除非使用 IN,否则在 where 或 order by 子句中使用类似的限制
我不拥有那本书,也不知道上下文。如果您执行WHERE foo IN (SELECT ...)
之类的操作,那么原因很明显。否则,该限制不存在。
它描述了一个标准的in (...)
结构,所以一般的说法显然是错误的。不过,对于那个特定的 sql 语句来说确实如此。这是误导。
【参考方案1】:
在您链接到的答案中,我会将其归类为“内联视图”或“内联查询”,而不是子查询。
当然,这引发了子查询到底是什么的问题。
这是一个您确实只能返回单列的示例。
select (select name from table where id = main_query.id),
id
from table main_query
这是一个可以返回多个列的示例。这似乎是明确的“相关”类型的子查询。
select id
from table main_query
where (col1, col2) in (select a,b
from c
where c.x = main_query.y);
这是一个示例,返回多少列并不重要,实际上任何值都会被忽略:
select id
from table main_query
where exists (select a,b
from c
where c.x = main_query.y);
总的来说,我认为这不是真的,但这取决于您对子查询的定义。
【讨论】:
可能想要为多列添加派生表示例。 EXISTS 也是这样,但事实是 EXISTS 忽略了列定义,所以它看到 5 列,*,SELECT 1 都是一样的 在第一个示例中,子查询必须返回 1 列 和 1 条记录(单个值)。我真的不知道仅对列数有任何一般限制。 别忘了SELECT * FROM (SELECT * FROM foo) bar
也是一个子查询。
@Matt 是的——我通常 SELECT NULL 只是为了支持所选值无关紧要的语义。这是一个有趣的 SQL 怪癖,真的。
@Shadow - 是的,正如你所说,只有一个值。【参考方案2】:
标量子查询只能返回一列。这些是在需要单个值的地方使用的子查询。这几乎可以出现在任何子句中。例如,当这个无意义的查询使用它们时:
select (select count(*) from information_schema.tables), table_name
from information_schema.columns
where table_name = (select table_name from information_schema.columns order by rand() limit 1);
但是,许多子查询不是标量子查询。其中包括:
FROM
子句中的子查询。
EXISTS
和 NOT EXISTS
的子查询。
在比较中使用元组运算符的子查询,例如=
和IN
。
【讨论】:
以上是关于声称子查询只能返回单个列的主要内容,如果未能解决你的问题,请参考以下文章