声称子查询只能返回单个列

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 子句中的子查询。 EXISTSNOT EXISTS 的子查询。 在比较中使用元组运算符的子查询,例如=IN

【讨论】:

以上是关于声称子查询只能返回单个列的主要内容,如果未能解决你的问题,请参考以下文章

子查询(章节摘要)

数据库子查询 ---where或having后面----列子查询-多行子查询

带有过程调用的 Oracle 多列子查询

子查询

mysql子查询

多表查询