相关子查询

相关子查询是引用不在其 FROM 子句中的列或表的子查询。该列可以在 Projection 子句或 WHERE 子句中。

通常,相关子查询会降低性能。建议使用表名或表别名限制子查询中的列名。从而除去与列所驻留的表相关的任何疑问。

下列查询是相关子查询的一个示例,它返回 orders 表中 10 个最近的装运日期的列表。它在子查询之后加上 ORDER BY 子句以对结果进行排序,原因是(除在 FROM 子句以外)您不能在子查询中包括 ORDER BY 。

图: 查询

SELECT po_num, ship_date FROM orders main
          WHERE 10 >
          (SELECT COUNT (DISTINCT ship_date)
          FROM orders sub
          WHERE sub.ship_date < main.ship_date)
          AND ship_date IS NOT NULL
          ORDER BY ship_date, po_num;

因为子查询产生的数取决于 main.ship_date(外部 SELECT 产生的一个值),所以该子查询是相关的。因此,必须对外部查询考虑的每一行重新执行子查询。

该查询使用 COUNT 函数来将值返回到主查询。然后,ORDER BY 子句对数据进行排序。查询找到并返回具有 10 个最新装运日期的 16 行,如下所示。

图: 查询结果

po_num     ship_date
          
          4745       06/21/1998
          278701     06/29/1998
          429Q       06/29/1998
          8052       07/03/1998
          B77897     07/03/1998
          LZ230      07/06/1998
          B77930     07/10/1998
          PC6782     07/12/1998
          DM354331   07/13/1998
          S22942     07/13/1998
          MA003      07/16/1998
          W2286      07/16/1998
          Z55709     07/16/1998
          C3288      07/25/1998
          KF2961     07/30/1998
          W9925      07/30/1998

如果对大型表使用相关子查询(如图 1),那么应对 ship_date 列建立索引以提高性能。否则,此 SELECT 语句效率降低,原因是它对表的每一行执行一次子查询。有关建立索引和性能问题的信息,请参阅 GBase 8s 管理员指南GBase 8s 性能指南

然而,不能在 FROM 子句中使用相关子查询,如下列无效示例所示:
SELECT item_num, stock_num FROM items, 
          (SELECT stock_num FROM catalog 
          WHERE stock_num = items.item_num) AS vtab;
该示例中的子查询具有错误 -24138:
ALL COLUMN REFERENCES IN A TABLE EXPRESSION MUST REFER
          TO TABLES IN THE FROM CLAUSE OF THE TABLE EXPRESSION.

数据库服务器发出该错误的原因是子查询中的 items.item_num 列还出现在外部查询的 Projection 子句中,但是内部查询的 FROM 子句仅指定 catalog 表。错误消息文本中的术语表表达式指的是 FROM 子句中的子查询返回的列值或表达式集合。而在 FROM 子句中,只有不相关子查询才是有效的。